Merge the last good pgo-green cset on mozilla-inbound to mozilla-central.

This commit is contained in:
Kyle Huey 2012-03-28 07:40:52 -07:00
commit 34b94a5666
248 changed files with 6485 additions and 4235 deletions

View File

@ -99,7 +99,9 @@ endif
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(topsrcdir)/other-licenses/atk-1.0 \
$(NULL)

View File

@ -42,12 +42,14 @@
#include "nsAccessibleWrap.h"
#include "nsAccUtils.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "nsMai.h"
#include "nsArrayUtils.h"
extern "C" {
using namespace mozilla::a11y;
extern "C" {
static AtkObject*
refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
{
@ -208,23 +210,17 @@ getRowExtentAtCB(AtkTable *aTable,
}
static AtkObject*
getCaptionCB(AtkTable *aTable)
getCaptionCB(AtkTable* aTable)
{
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return nsnull;
nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return nsnull;
nsCOMPtr<nsIAccessibleTable> accTable;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
getter_AddRefs(accTable));
NS_ENSURE_TRUE(accTable, nsnull);
TableAccessible* table = accWrap->AsTable();
NS_ENSURE_TRUE(table, nsnull);
nsCOMPtr<nsIAccessible> caption;
nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
if (NS_FAILED(rv) || !caption)
return nsnull;
return nsAccessibleWrap::GetAtkObject(caption);
nsAccessible* caption = table->Caption();
return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull;
}
static const gchar*

View File

@ -44,9 +44,6 @@
#include "nsApplicationAccessibleWrap.h"
#include "nsDocAccessible.h"
#include "nsIAccessibleText.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
#endif
#include "nsAccEvent.h"
#include "States.h"

View File

@ -104,8 +104,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/style \

View File

@ -58,7 +58,7 @@ using namespace mozilla::a11y;
nsARIAGridAccessible::
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsAccessibleWrap(aContent, aDoc)
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -70,21 +70,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible,
nsIAccessibleTable)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleTable
//nsAccessNode
NS_IMETHODIMP
nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption)
void
nsARIAGridAccessible::Shutdown()
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
// XXX: should be pointed by aria-labelledby on grid?
return NS_ERROR_NOT_IMPLEMENTED;
mTable = nsnull;
nsAccessibleWrap::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleTable
NS_IMETHODIMP
nsARIAGridAccessible::GetSummary(nsAString &aSummary)
{
@ -710,15 +707,6 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
return NS_OK;
}
NS_IMETHODIMP
nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// Protected

View File

@ -42,12 +42,16 @@
#include "nsIAccessibleTable.h"
#include "nsHyperTextAccessibleWrap.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
/**
* Accessible for ARIA grid and treegrid.
*/
class nsARIAGridAccessible : public nsAccessibleWrap,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
@ -56,7 +60,13 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable
NS_DECL_NSIACCESSIBLETABLE
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
// nsAccessNode
virtual void Shutdown();
protected:
/**

View File

@ -47,9 +47,7 @@
#include "nsARIAMap.h"
#include "nsDocAccessible.h"
#include "nsHyperTextAccessible.h"
#include "nsHTMLTableAccessible.h"
#include "nsTextAccessible.h"
#include "nsXULTreeGridAccessible.h"
#include "nsIDOMXULContainerElement.h"
#include "nsIDOMXULSelectCntrlEl.h"

View File

@ -66,6 +66,11 @@ class nsHTMLImageMapAccessible;
class nsHTMLLIAccessible;
struct nsRoleMapEntry;
class Relation;
namespace mozilla {
namespace a11y {
class TableAccessible;
}
}
class nsTextAccessible;
struct nsRect;
@ -471,6 +476,8 @@ public:
inline bool IsRoot() const { return mFlags & eRootAccessible; }
nsRootAccessible* AsRoot();
virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
nsTextAccessible* AsTextLeaf();

View File

@ -41,15 +41,13 @@
#include "nsCaretAccessible.h"
#include "nsDocAccessibleWrap.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
#endif
#include "nsHashtable.h"
#include "nsCaretAccessible.h"
#include "nsIDocument.h"
#include "nsIDOMEventListener.h"
class nsXULTreeAccessible;
class Relation;
#define NS_ROOTACCESSIBLE_IMPL_CID \

View File

@ -0,0 +1,170 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef TABLE_ACCESSIBLE_H
#define TABLE_ACCESSIBLE_H
#include "nsString.h"
#include "nsTArray.h"
#include "prtypes.h"
class nsAccessible;
namespace mozilla {
namespace a11y {
/**
* Accessible table interface.
*/
class TableAccessible
{
public:
/**
* Return the caption accessible if any for this table.
*/
virtual nsAccessible* Caption() { return nsnull; }
/**
* Get the summary for this table.
*/
virtual void Summary(nsString& aSummary) { aSummary.Truncate(); }
/**
* Return the number of columns in the table.
*/
virtual PRUint32 ColCount() { return 0; }
/**
* Return the number of rows in the table.
*/
virtual PRUint32 RowCount() { return 0; }
/**
* Return the accessible for the cell at the given row and column indices.
*/
virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; }
/**
* Return the index of the cell at the given row and column.
*/
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
/**
* Return the column index of the cell with the given index.
*/
virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; }
/**
* Return the row index of the cell with the given index.
*/
virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; }
/**
* Get the row and column indices for the cell at the given index.
*/
virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx,
PRInt32* aColIdx) {}
/**
* Return the number of columns occupied by the cell at the given row and
* column indices.
*/
virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
/**
* Return the number of rows occupied by the cell at the given row and column
* indices.
*/
virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
/**
* Get the description of the given column.
*/
virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription)
{ aDescription.Truncate(); }
/**
* Get the description for the given row.
*/
virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription)
{ aDescription.Truncate(); }
/**
* Return true if the given column is selected.
*/
virtual bool IsColSelected(PRUint32 aColIdx) { return false; }
/**
* Return true if the given row is selected.
*/
virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; }
/**
* Return true if the given cell is selected.
*/
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; }
/**
* Return the number of selected cells.
*/
virtual PRUint32 SelectedCellCount() { return 0; }
/**
* Return the number of selected columns.
*/
virtual PRUint32 SelectedColCount() { return 0; }
/**
* Return the number of selected rows.
*/
virtual PRUint32 SelectedRowCount() { return 0; }
/**
* Get the set of selected cells.
*/
virtual void SelectedCells(nsTArray<nsAccessible*>* aCells) {}
/**
* Get the set of selected column indices.
*/
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols) {}
/**
* Get the set of selected row indices.
*/
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows) {}
/**
* Select the given column unselecting any other selected columns.
*/
virtual void SelectCol(PRUint32 aColIdx) {}
/**
* Select the given row unselecting all other previously selected rows.
*/
virtual void SelectRow(PRUint32 aRowIdx) {}
/**
* Unselect the given column leaving other selected columns selected.
*/
virtual void UnselectCol(PRUint32 aColIdx) {}
/**
* Unselect the given row leaving other selected rows selected.
*/
virtual void UnselectRow(PRUint32 aRowIdx) {}
/**
* Return true if the table is probably for layout.
*/
virtual bool IsProbablyLayoutTable() { return false; }
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -73,6 +73,8 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)

View File

@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole()
nsHTMLTableAccessible::
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsAccessibleWrap(aContent, aDoc)
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -446,6 +446,16 @@ nsHTMLTableAccessible::
NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
nsHTMLTableAccessible, nsIAccessibleTable)
////////////////////////////////////////////////////////////////////////////////
//nsAccessNode
void
nsHTMLTableAccessible::Shutdown()
{
mTable = nsnull;
nsAccessibleWrap::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLTableAccessible: nsAccessible implementation
@ -511,9 +521,7 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
NS_ENSURE_SUCCESS(rv, rv);
bool isProbablyForLayout;
IsProbablyForLayout(&isProbablyForLayout);
if (isProbablyForLayout) {
if (IsProbablyLayoutTable()) {
nsAutoString oldValueUnused;
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
NS_LITERAL_STRING("true"), oldValueUnused);
@ -538,13 +546,11 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType)
////////////////////////////////////////////////////////////////////////////////
// nsHTMLTableAccessible: nsIAccessibleTable implementation
NS_IMETHODIMP
nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
nsAccessible*
nsHTMLTableAccessible::Caption()
{
NS_ENSURE_ARG_POINTER(aCaption);
NS_IF_ADDREF(*aCaption = Caption());
return NS_OK;
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
return child && child->Role() == roles::CAPTION ? child : nsnull;
}
NS_IMETHODIMP
@ -1307,8 +1313,7 @@ nsHTMLTableAccessible::Description(nsString& aDescription)
#ifdef SHOW_LAYOUT_HEURISTIC
if (aDescription.IsEmpty()) {
bool isProbablyForLayout;
IsProbablyForLayout(&isProbablyForLayout);
bool isProbablyForLayout = IsProbablyLayoutTable();
aDescription = mLayoutHeuristic;
}
#ifdef DEBUG_A11Y
@ -1357,8 +1362,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
return !!foundItem;
}
NS_IMETHODIMP
nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
bool
nsHTMLTableAccessible::IsProbablyLayoutTable()
{
// Implement a heuristic to determine if table is most likely used for layout
// XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
@ -1370,18 +1375,16 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
// Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
#ifdef SHOW_LAYOUT_HEURISTIC
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
{ *aIsProbablyForLayout = isLayout; \
mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
{ \
mLayoutHeuristic = isLayout ? \
NS_LITERAL_STRING("layout table: " heuristic) : \
NS_LITERAL_STRING("data table: " heuristic); \
return isLayout; \
}
#else
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; }
#endif
*aIsProbablyForLayout = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsDocAccessible* docAccessible = Document();
if (docAccessible) {
PRUint64 docState = docAccessible->State();

View File

@ -41,6 +41,8 @@
#include "nsHyperTextAccessibleWrap.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
class nsITableLayout;
class nsITableCellLayout;
@ -121,16 +123,28 @@ public:
}
class nsHTMLTableAccessible : public nsAccessibleWrap,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
// nsIAccessible Table
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// TableAccessible
virtual nsAccessible* Caption();
virtual bool IsProbablyLayoutTable();
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual void Description(nsString& aDescription);
virtual nsresult GetNameInternal(nsAString& aName);
virtual mozilla::a11y::role NativeRole();
@ -138,13 +152,6 @@ public:
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
virtual Relation RelationByType(PRUint32 aRelationType);
// TableAccessible
inline nsAccessible* Caption() const
{
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull;
}
// nsHTMLTableAccessible
/**

View File

@ -132,7 +132,7 @@ nsHyperTextAccessible::NativeRole()
return roles::FORM;
if (tag == nsGkAtoms::blockquote || tag == nsGkAtoms::div ||
tag == nsGkAtoms::nav)
tag == nsGkAtoms::section || tag == nsGkAtoms::nav)
return roles::SECTION;
if (tag == nsGkAtoms::h1 || tag == nsGkAtoms::h2 ||
@ -1239,6 +1239,9 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
if (mContent->Tag() == nsGkAtoms::nav)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("navigation"));
else if (mContent->Tag() == nsGkAtoms::section)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("region"));
else if (mContent->Tag() == nsGkAtoms::footer)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("contentinfo"));

View File

@ -114,7 +114,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../content/base/src \
-I$(srcdir)/../../../content/events/src \

View File

@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsAccEvent.cpp \
nsAccessibleRelation.cpp \
xpcAccessibleTable.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
@ -59,4 +60,5 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
$(NULL)

View File

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xpcAccessibleTable.h"
#include "nsAccessible.h"
#include "TableAccessible.h"
nsresult
xpcAccessibleTable::GetCaption(nsIAccessible** aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
if (!mTable)
return NS_ERROR_FAILURE;
NS_IF_ADDREF(*aCaption = mTable->Caption());
return NS_OK;
}
nsresult
xpcAccessibleTable::IsProbablyForLayout(bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
if (!mTable)
return NS_ERROR_FAILURE;
*aResult = mTable->IsProbablyLayoutTable();
return NS_OK;
}

View File

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
#include "nscore.h"
class nsIAccessible;
namespace mozilla {
namespace a11y {
class TableAccessible;
}
}
class xpcAccessibleTable
{
public:
xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
nsresult GetCaption(nsIAccessible** aCaption);
nsresult IsProbablyForLayout(bool* aIsForLayout);
protected:
mozilla::a11y::TableAccessible* mTable;
};
#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
{ return xpcAccessibleTable::GetCaption(aCaption); } \
NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \
NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \
NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \
NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
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 GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \
NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \
NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \
NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \
NS_IMETHOD IsProbablyForLayout(bool* aResult) \
{ return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_

View File

@ -72,7 +72,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)

View File

@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
nsXULListboxAccessible::
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
XULSelectControlAccessible(aContent, aDoc)
XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
{
nsIContent* parentContent = mContent->GetParent();
if (parentContent) {
@ -164,6 +164,16 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
return NS_ERROR_NO_INTERFACE;
}
////////////////////////////////////////////////////////////////////////////////
//nsAccessNode
void
nsXULListboxAccessible::Shutdown()
{
mTable = nsnull;
XULSelectControlAccessible::Shutdown();
}
bool
nsXULListboxAccessible::IsMulticolumn()
{
@ -229,15 +239,6 @@ nsXULListboxAccessible::NativeRole()
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible. nsIAccessibleTable
NS_IMETHODIMP
nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSummary(nsAString &aSummary)
{
@ -820,15 +821,6 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible: Widgets

View File

@ -40,11 +40,12 @@
#ifndef __nsXULListboxAccessible_h__
#define __nsXULListboxAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsCOMPtr.h"
#include "nsXULMenuAccessible.h"
#include "nsBaseWidgetAccessible.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
#include "XULSelectControlAccessible.h"
class nsIWeakReference;
@ -90,19 +91,27 @@ public:
* A class the represents the XUL Listbox widget.
*/
class nsXULListboxAccessible : public XULSelectControlAccessible,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
virtual ~nsXULListboxAccessible() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
// nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsIAccessible
NS_IMETHOD GetValue(nsAString& aValue);
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual mozilla::a11y::role NativeRole();
virtual PRUint64 NativeState();

View File

@ -58,7 +58,7 @@ using namespace mozilla::a11y;
nsXULTreeGridAccessible::
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsXULTreeAccessible(aContent, aDoc)
nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -72,15 +72,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridAccessible: nsIAccessibleTable implementation
NS_IMETHODIMP
nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
{
@ -570,13 +561,14 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridAccessible: nsAccessNode implementation
return NS_OK;
void
nsXULTreeGridAccessible::Shutdown()
{
mTable = nsnull;
nsXULTreeAccessible::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -39,15 +39,17 @@
#ifndef __nsXULTreeGridAccessible_h__
#define __nsXULTreeGridAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsXULTreeAccessible.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
/**
* Represents accessible for XUL tree in the case when it has multiple columns.
*/
class nsXULTreeGridAccessible : public nsXULTreeAccessible,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
@ -56,9 +58,13 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable
NS_DECL_NSIACCESSIBLETABLE
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual mozilla::a11y::role NativeRole();
protected:

View File

@ -24,6 +24,7 @@
testRole("footer", ROLE_FOOTER);
testRole("article", ROLE_DOCUMENT);
testRole("aside", ROLE_NOTE);
testRole("section", ROLE_SECTION); // XXX bug 739612: not a landmark
testRole("main", ROLE_DOCUMENT);
testRole("form", ROLE_FORM);
@ -32,6 +33,7 @@
testAttrs("nav", {"xml-roles" : "navigation"}, true);
testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
testAttrs("aside", {"xml-roles" : "complementary"}, true);
testAttrs("section", {"xml-roles" : "region"}, true);
testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
testAttrs("form", {"xml-roles" : "form"}, true);
@ -41,6 +43,7 @@
testAttrs("footer", {"tag" : "footer"}, true);
testAttrs("article", {"tag" : "article"}, true);
testAttrs("aside", {"tag" : "aside"}, true);
testAttrs("section", {"tag" : "section"}, true);
testAttrs("main", {"tag" : "article"}, true);
testAttrs("form", {"tag" : "article"}, true);
@ -68,6 +71,11 @@
title="Change implementation of HTML5 landmark elements to conform">
Bug 610650
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
title="Map section to pane (like role=region)">
Mozilla Bug 614310
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
title="Map ARIA role FORM">
@ -82,6 +90,7 @@
<header id="header">a header</header>
<footer id="footer">a footer</footer>
<aside id="aside">by the way I am an aside</aside>
<section id="section">a section</section>
<article id="article">an article</article>
<article id="main" role="main">a main area</article>

View File

@ -53,6 +53,7 @@ const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;

View File

@ -57,6 +57,7 @@ _TEST_FILES =\
test_imagemap.html \
test_list_editabledoc.html \
test_list.html \
test_listbox.xul \
test_menu.xul \
test_menubutton.xul \
test_recreation.html \

View File

@ -0,0 +1,180 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL listbox hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function insertListitem(aListboxID)
{
this.listboxNode = getNode(aListboxID);
this.listitemNode = document.createElement("listitem");
this.listitemNode.setAttribute("label", "item1");
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.listitemNode),
new invokerChecker(EVENT_REORDER, this.listboxNode)
];
this.invoke = function insertListitem_invoke()
{
this.listboxNode.insertBefore(this.listitemNode,
this.listboxNode.firstChild);
}
this.finalCheck = function insertListitem_finalCheck()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item1"
},
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree(this.listboxNode, tree);
}
this.getID = function insertListitem_getID()
{
return "insert listitem ";
}
}
function removeListitem(aListboxID)
{
this.listboxNode = getNode(aListboxID);
this.listitemNode = null;
this.listitem;
function getListitem(aThisObj)
{
return aThisObj.listitem;
}
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getListitem, this),
new invokerChecker(EVENT_REORDER, this.listboxNode)
];
this.invoke = function removeListitem_invoke()
{
this.listitemNode = this.listboxNode.firstChild;
this.listitem = getAccessible(this.listitemNode);
this.listboxNode.removeChild(this.listitemNode);
}
this.finalCheck = function removeListitem_finalCheck()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree(this.listboxNode, tree);
}
this.getID = function removeListitem_getID()
{
return "remove listitem ";
}
}
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree("listbox", tree);
gQueue = new eventQueue();
gQueue.push(new insertListitem("listbox"));
gQueue.push(new removeListitem("listbox"));
gQueue.invoke(); // Will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=656225"
title="XUL listbox accessible tree doesn't get updated">
Mozilla Bug 656225
</a>
<br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<listbox id="listbox" rows="2">
<listitem label="item2"/>
<listitem label="item3"/>
<listitem label="item4"/>
</listbox>
</vbox>
</hbox>
</window>

View File

@ -69,3 +69,4 @@ fi
MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
MOZ_EXTENSION_MANAGER=1
ENABLE_MARIONETTE=1

View File

@ -56,13 +56,14 @@ DIRS = \
app \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
ifdef MAKENSISU
DIRS += installer/windows
endif
include $(topsrcdir)/config/rules.mk
ifeq ($(OS_ARCH),WINNT)
ifdef MAKENSISU
# For Windows build the uninstaller during the application build since the
# uninstaller is included with the application for mar file generation.
libs::

View File

@ -8663,6 +8663,31 @@ let gPrivateBrowsingUI = {
get privateBrowsingEnabled() {
return this._privateBrowsingService.privateBrowsingEnabled;
},
/**
* These accessors are used to support per-window Private Browsing mode.
* For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
* and the setter should only be used in tests.
*/
get privateWindow() {
return window.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow)
.docShell.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing;
},
set privateWindow(val) {
return window.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow)
.docShell.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing = val;
}
};

View File

@ -193,9 +193,9 @@ PrivateBrowsingService.prototype = {
if (!this._quitting && this._saveSession) {
let browserWindow = this._getBrowserWindow();
// if there are open browser windows, load a dummy session to get a distinct
// if there are open browser windows, load a dummy session to get a distinct
// separation between private and non-private sessions
if (browserWindow) {
if (browserWindow) {
// set an empty session to transition from/to pb mode, see bug 476463
ss.setBrowserState(blankState);
@ -217,7 +217,9 @@ PrivateBrowsingService.prototype = {
.getInterface(Ci.nsIXULWindow)
.docShell.contentViewer.resetCloseWindow();
}
}
if (!this._quitting) {
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
var window = windowsEnum.getNext();

View File

@ -58,21 +58,31 @@ function test() {
ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
ok(pbMenuItem, "The Private Browsing menu item exists");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
gPrivateBrowsingUI.toggleMode();
is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
// check to see if the Private Browsing mode was activated successfully
is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
gPrivateBrowsingUI.toggleMode()
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
// check to see if the Private Browsing mode was deactivated successfully
is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
// These are tests for the privateWindow setter. Note that the setter should
// not be used anywhere else for now!
gPrivateBrowsingUI.privateWindow = true;
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
gPrivateBrowsingUI.privateWindow = false;
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
// now, test using the <command> object
let cmd = document.getElementById("Tools:PrivateBrowsing");
isnot(cmd, null, "XUL command object for the private browsing service exists");

View File

@ -102,7 +102,7 @@ if [ "$MOZ_SAFE_BROWSING" ]; then
"
fi
if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
if [ "$MAKENSISU" ]; then
add_makefiles "
browser/installer/windows/Makefile
"

View File

@ -41,6 +41,7 @@ package @ANDROID_PACKAGE_NAME@;
public interface Assert {
void dumpLog(String message);
void dumpLog(String message, Throwable t);
void setLogFile(String filename);
void setTestName(String testName);

View File

@ -66,6 +66,11 @@ public class FennecMochitestAssert implements Assert {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
}
/** Write information to a logfile and logcat */
public void dumpLog(String message, Throwable t) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
}
/** Set the filename used for dumpLog. */
public void setLogFile(String filename) {
FennecNativeDriver.setLogFile(filename);

View File

@ -41,7 +41,6 @@ package @ANDROID_PACKAGE_NAME@;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileReader;
@ -49,6 +48,7 @@ import java.io.FileWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;
@ -459,41 +459,48 @@ public class FennecNativeDriver implements Driver {
}
public static void log(LogLevel level, String message) {
log(level, message, null);
}
public static void log(LogLevel level, Throwable t) {
log(level, null, t);
}
public static void log(LogLevel level, String message, Throwable t) {
if (mLogFile == null) {
assert(false);
}
if (level.isEnabled(mLogLevel)) {
File file = new File(mLogFile);
BufferedWriter bw = null;
PrintWriter pw = null;
try {
bw = new BufferedWriter(new FileWriter(mLogFile, true));
bw.write(message);
bw.newLine();
} catch(IOException e) {
pw = new PrintWriter(new FileWriter(mLogFile, true));
if (message != null) {
pw.println(message);
}
if (t != null) {
t.printStackTrace(pw);
}
} catch (IOException ioe) {
Log.e("Robocop", "exception with file writer on: " + mLogFile);
} finally {
try {
if (bw != null) {
bw.flush();
bw.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
pw.close();
}
// PrintWriter doesn't throw IOE but sets an error flag instead,
// so check for that
if (pw.checkError()) {
Log.e("Robocop", "exception with file writer on: " + mLogFile);
}
}
if (level == LogLevel.LOG_LEVEL_INFO) {
Log.i("Robocop", message);
Log.i("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_DEBUG) {
Log.d("Robocop", message);
Log.d("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_WARN) {
Log.w("Robocop", message);
Log.w("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_ERROR) {
Log.e("Robocop", message);
Log.e("Robocop", message, t);
}
}
}

View File

@ -49,6 +49,11 @@ public class FennecTalosAssert implements Assert {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
}
/** Write information to a logfile and logcat */
public void dumpLog(String message, Throwable t) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
}
/**
* Set the filename used for dumpLog.
*/

View File

@ -127,8 +127,8 @@ classes.dex: $(_JAVA_TESTS)
$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
robocop.ap_: AndroidManifest.xml
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./
robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
robocop.apk: robocop.ap_ classes.dex
cp $(TESTPATH)/robocop.ini robocop.ini

View File

@ -265,9 +265,9 @@ build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
stage1_tool_inst_dir = stage1_dir + '/inst'
stage2_dir = build_dir + '/stage2'
build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
"CXX" : stage1_tool_inst_dir + "/bin/g++",
"AR" : stage1_tool_inst_dir + "/bin/ar",
build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
"CC" : "gcc -fgnu89-inline",
"CXX" : "g++",
"RANLIB" : "true" },
stage2_dir, False)

View File

@ -6319,29 +6319,38 @@ dnl ========================================================
dnl Installer
dnl ========================================================
dnl Abort Windows build if the required major version and
dnl minimum minor version of Unicode NSIS isn't in the path.
dnl minimum minor version of Unicode NSIS isn't in the path
dnl (unless in case of cross compiling, for which Unicode
dnl is not yet sufficient).
if test "$OS_ARCH" = "WINNT"; then
REQ_NSIS_MAJOR_VER=2
MIN_NSIS_MINOR_VER=33
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
AC_MSG_RESULT([yes])
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" || \
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
if test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
else
MAKENSISU=
fi
fi
elif test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
else
MAKENSISU=
fi
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" ||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
fi
AC_MSG_RESULT([yes])
fi
AC_MSG_CHECKING([for tar archiver])
@ -6458,14 +6467,6 @@ MOZ_ARG_DISABLE_BOOL(tests,
ENABLE_TESTS=,
ENABLE_TESTS=1 )
dnl ========================================================
dnl Marionette
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(marionette,
[ --enable-marionette Enable Marionette for remote testing and control],
ENABLE_MARIONETTE=1,
ENABLE_MARIONETTE)
dnl ========================================================
dnl parental controls (for Windows Vista)
dnl ========================================================

View File

@ -19,6 +19,7 @@
* Contributor(s):
* Sid Stamm <sid@mozilla.com>
* Brandon Sterne <bsterne@mozilla.com>
* Ian Melven <imelven@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -301,7 +302,7 @@ ContentSecurityPolicy.prototype = {
var failure = function(aEvt) {
if (req.readyState == 4 && req.status != 200) {
CSPError("Failed to send report to " + reportURI);
CSPError("Failed to send report to " + uris[i]);
}
};
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
@ -313,6 +314,10 @@ ContentSecurityPolicy.prototype = {
req.upload.addEventListener("error", failure, false);
req.upload.addEventListener("abort", failure, false);
// we need to set an nsIChannelEventSink on the XHR object
// so we can tell it to not follow redirects when posting the reports
req.channel.notificationCallbacks = new CSPReportRedirectSink();
req.send(JSON.stringify(report));
CSPdebug("Sent violation report to " + uris[i]);
} catch(e) {
@ -494,4 +499,54 @@ ContentSecurityPolicy.prototype = {
},
};
// The POST of the violation report (if it happens) should not follow
// redirects, per the spec. hence, we implement an nsIChannelEventSink
// with an object so we can tell XHR to abort if a redirect happens.
function CSPReportRedirectSink() {
}
CSPReportRedirectSink.prototype = {
QueryInterface: function requestor_qi(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIInterfaceRequestor) ||
iid.equals(Ci.nsIChannelEventSink))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
// nsIInterfaceRequestor
getInterface: function requestor_gi(iid) {
if (iid.equals(Ci.nsIChannelEventSink))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
// nsIChannelEventSink
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
flags, callback) {
CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
" failed, as a redirect occurred");
// cancel the old channel so XHR failure callback happens
oldChannel.cancel(Cr.NS_ERROR_ABORT);
// notify an observer that we have blocked the report POST due to a redirect,
// used in testing, do this async since we're in an async call now to begin with
Services.tm.mainThread.dispatch(
function() {
observerSubject = Cc["@mozilla.org/supports-cstring;1"]
.createInstance(Ci.nsISupportsCString);
observerSubject.data = oldChannel.URI.asciiSpec;
Services.obs.notifyObservers(observerSubject,
CSP_VIOLATION_TOPIC,
"denied redirect while sending violation report");
}, Ci.nsIThread.DISPATCH_NORMAL);
// throw to stop the redirect happening
throw Cr.NS_BINDING_REDIRECTED;
}
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]);

View File

@ -378,3 +378,29 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
static PLDHashOperator
TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
{
if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
JSTracer* trc = static_cast<JSTracer *>(aClosure);
JS_CALL_OBJECT_TRACER(trc, global, "active window global");
}
}
return PL_DHASH_NEXT;
}
void
mozilla::dom::TraceBlackJS(JSTracer* aTrc)
{
if (!nsCCUncollectableMarker::sGeneration) {
return;
}
// Mark globals of active windows black.
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (windowsById) {
windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
}
}

View File

@ -38,6 +38,8 @@
#include "nsIObserver.h"
#include "nsCycleCollectionParticipant.h"
struct JSTracer;
class nsCCUncollectableMarker : public nsIObserver
{
NS_DECL_ISUPPORTS
@ -56,10 +58,10 @@ class nsCCUncollectableMarker : public nsIObserver
return aGeneration && aGeneration == sGeneration;
}
static bool InGeneration(nsCycleCollectionTraversalCallback &cb,
static bool InGeneration(nsCycleCollectionTraversalCallback& aCb,
PRUint32 aGeneration)
{
return InGeneration(aGeneration) && !cb.WantAllTraces();
return InGeneration(aGeneration) && !aCb.WantAllTraces();
}
static PRUint32 sGeneration;
@ -68,3 +70,9 @@ private:
nsCCUncollectableMarker() {}
};
namespace mozilla {
namespace dom {
void TraceBlackJS(JSTracer* aTrc);
}
}

View File

@ -2547,6 +2547,7 @@ void
nsDocument::StopDocumentLoad()
{
if (mParser) {
mParserAborted = true;
mParser->Terminate();
}
}

View File

@ -1188,6 +1188,10 @@ protected:
// our presshell. This is used to handle flush reentry correctly.
bool mInFlush:1;
// Parser aborted. True if the parser of this document was forcibly
// terminated instead of letting it finish at its own pace.
bool mParserAborted:1;
PRUint8 mXMLDeclarationBits;
nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;

View File

@ -1935,7 +1935,8 @@ GK_ATOM(VolumeUp, "VolumeUp")
GK_ATOM(VolumeDown, "VolumeDown")
GK_ATOM(Menu, "Menu")
// Smooth scroll profiles
// Smooth scroll events origins
GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse)
GK_ATOM(pixels, "pixels")
GK_ATOM(lines, "lines")
GK_ATOM(pages, "pages")

View File

@ -314,42 +314,32 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
mCurrentRequestNeedsResetAnimation = false;
}
// We just loaded all the data we're going to get. If we haven't done an
// initial paint, we want to make sure the image starts decoding for 2
// reasons:
// We just loaded all the data we're going to get. If we're visible and
// haven't done an initial paint (*), we want to make sure the image starts
// decoding immediately, for two reasons:
//
// 1) This image is sitting idle but might need to be decoded as soon as we
// start painting, in which case we've wasted time.
//
// 2) We want to block onload until all visible images are decoded. We do this
// by blocking onload until all in progress decodes get at least one frame
// by blocking onload until all in-progress decodes get at least one frame
// decoded. However, if all the data comes in while painting is suppressed
// (ie, before the initial paint delay is finished), we fire onload without
// doing a paint first. This means that decode-on-draw images don't start
// decoding, so we can't wait for them to finish. See bug 512435.
//
// (*) IsPaintingSuppressed returns false if we haven't gotten the initial
// reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
// It's possible for painting to be suppressed for reasons other than the
// initial paint delay (for example, being in the bfcache), but we probably
// aren't loading images in those situations.
// We can only do this if we have a presshell
nsIDocument* doc = GetOurDocument();
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
if (shell) {
// We need to figure out whether to kick off decoding
bool doRequestDecode = false;
if (shell && shell->IsVisible() &&
(!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
// If we haven't got the initial reflow yet, IsPaintingSuppressed actually
// returns false
if (!shell->DidInitialReflow())
doRequestDecode = true;
// Figure out if painting is suppressed. Note that it's possible for painting
// to be suppressed for reasons other than the initial paint delay (for
// example - being in the bfcache), but we probably aren't loading images in
// those situations.
if (shell->IsPaintingSuppressed())
doRequestDecode = true;
// If we're requesting a decode, do it
if (doRequestDecode)
mCurrentRequest->RequestDecode();
mCurrentRequest->RequestDecode();
}
// Fire the appropriate DOM event.

View File

@ -2768,10 +2768,13 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
// Create our listener
nsCOMPtr<nsIStreamListener> listener = this;
if (mState & XML_HTTP_REQUEST_MULTIPART) {
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
listener = new nsMultipartProxyListener(listener);
if (!listener) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
}
// Blocking gets are common enough out of XHR that we should mark

View File

@ -572,6 +572,12 @@ _TEST_FILES2 = \
test_bug737612.html \
test_bug738108.html \
test_bug366944.html \
test_bug650386_redirect_301.html \
test_bug650386_redirect_302.html \
test_bug650386_redirect_303.html \
test_bug650386_redirect_307.html \
file_bug650386_content.sjs \
file_bug650386_report.sjs \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1,37 @@
// SJS file for tests for bug650386, serves file_bug650386_content.html
// with a CSP that will trigger a violation and that will report it
// to file_bug650386_report.sjs
//
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
// returned/type of redirect to do comes from the query string
// parameter passed in from the test_bug650386_* files and then also
// uses that value in the report-uri parameter of the CSP
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache", false);
// this gets used in the CSP as part of the report URI.
var redirect = request.queryString;
if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) {
// if we somehow got some bogus redirect code here,
// do a 302 redirect to the same URL as the report URI
// redirects to - this will fail the test.
var loc = "http://example.com/some/fake/path";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", loc, false);
return;
}
var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect;
response.setHeader("X-Content-Security-Policy", csp, false);
// the actual file content.
// this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
// specified by the CSP string above.
var content = "<!DOCTYPE HTML><html><body><img src = \"http://some.other.domain.example.com\"></body></html>";
response.write(content);
return;
}

View File

@ -0,0 +1,16 @@
// SJS file for tests for bug650386, this serves as CSP violation report target
// and issues a redirect, to make sure the browser does not post to the target
// of the redirect, per CSP spec.
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
// returned/type of redirect to do comes from the query string
// parameter
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache", false);
var redirect = request.queryString;
var loc = "http://example.com/some/fake/path";
response.setStatusLine("1.1", redirect, "Found");
response.setHeader("Location", loc, false);
return;
}

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
Test that CSP violation reports are not sent when a 301 redirect is encountered
-->
<head>
<title>Test for Bug 650386</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id = "content_iframe"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 650386 **/
// This is used to watch the redirect of the report POST get blocked
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
SpecialPowers.addObserver(this, "http-on-modify-request", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "http-on-modify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
if (asciiSpec == "http://example.com/some/fake/path")
window.done(false);
}
if(topic === "csp-on-violate-policy") {
// something was blocked, but we are looking specifically for the redirect being blocked
if (data == "denied redirect while sending violation report")
window.done(true);
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
SpecialPowers.removeObserver(this, "http-on-modify-request");
}
}
window.examiner = new examiner();
// result == true if we saw the redirect blocked notify, false if we saw the post
// to the redirect target go out
window.done = function(result) {
ok(result, "a 301 redirect when posting violation report should be blocked");
// clean up observers and finish the test
window.examiner.remove();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?301';
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
Test that CSP violation reports are not sent when a 302 redirect is encountered
-->
<head>
<title>Test for Bug 650386</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id = "content_iframe"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 650386 **/
// This is used to watch the redirect of the report POST get blocked
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
SpecialPowers.addObserver(this, "http-on-modify-request", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "http-on-modify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
if (asciiSpec == "http://example.com/some/fake/path")
window.done(false);
}
if(topic === "csp-on-violate-policy") {
// something was blocked, but we are looking specifically for the redirect being blocked
if (data == "denied redirect while sending violation report")
window.done(true);
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
SpecialPowers.removeObserver(this, "http-on-modify-request");
}
}
window.examiner = new examiner();
// result == true if we saw the redirect blocked notify, false if we saw the post
// to the redirect target go out
window.done = function(result) {
ok(result, "a 302 redirect when posting violation report should be blocked");
// clean up observers and finish the test
window.examiner.remove();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?302';
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
Test that CSP violation reports are not sent when a 303 redirect is encountered
-->
<head>
<title>Test for Bug 650386</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id = "content_iframe"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 650386 **/
// This is used to watch the redirect of the report POST get blocked
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
SpecialPowers.addObserver(this, "http-on-modify-request", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "http-on-modify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
if (asciiSpec == "http://example.com/some/fake/path")
window.done(false);
}
if(topic === "csp-on-violate-policy") {
// something was blocked, but we are looking specifically for the redirect being blocked
if (data == "denied redirect while sending violation report")
window.done(true);
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
SpecialPowers.removeObserver(this, "http-on-modify-request");
}
}
window.examiner = new examiner();
// result == true if we saw the redirect blocked notify, false if we saw the post
// to the redirect target go out
window.done = function(result) {
ok(result, "a 303 redirect when posting violation report should be blocked");
// clean up observers and finish the test
window.examiner.remove();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?303';
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
Test that CSP violation reports are not sent when a 307 redirect is encountered
-->
<head>
<title>Test for Bug 650386</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id = "content_iframe"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 650386 **/
// This is used to watch the redirect of the report POST get blocked
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
SpecialPowers.addObserver(this, "http-on-modify-request", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "http-on-modify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
if (asciiSpec == "http://example.com/some/fake/path")
window.done(false);
}
if(topic === "csp-on-violate-policy") {
// something was blocked, but we are looking specifically for the redirect being blocked
if (data == "denied redirect while sending violation report")
window.done(true);
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
SpecialPowers.removeObserver(this, "http-on-modify-request");
}
}
window.examiner = new examiner();
// result == true if we saw the redirect blocked notify, false if we saw the post
// to the redirect target go out
window.done = function(result) {
ok(result, "a 307 redirect when posting violation report should be blocked");
// clean up observers and finish the test
window.examiner.remove();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?307';
</script>
</pre>
</body>
</html>

View File

@ -2695,7 +2695,8 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
nsMouseScrollEvent* aMouseEvent,
nsIScrollableFrame::ScrollUnit aScrollQuantity,
bool aAllowScrollSpeedOverride,
nsQueryContentEvent* aQueryEvent)
nsQueryContentEvent* aQueryEvent,
nsIAtom *aOrigin)
{
nsIScrollableFrame* frameToScroll = nsnull;
nsIFrame* scrollFrame = aTargetFrame;
@ -2857,7 +2858,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
nsIntPoint overflow;
frameToScroll->ScrollBy(nsIntPoint(scrollX, scrollY), aScrollQuantity,
mode, &overflow);
mode, &overflow, aOrigin);
aMouseEvent->scrollOverflow = isHorizontal ? overflow.x : overflow.y;
return NS_OK;
}
@ -2867,7 +2868,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
if (newFrame)
return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
aAllowScrollSpeedOverride, aQueryEvent);
aAllowScrollSpeedOverride, aQueryEvent, aOrigin);
}
aMouseEvent->scrollOverflow = numLines;
@ -3213,7 +3214,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
switch (action) {
case MOUSE_SCROLL_N_LINES:
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::LINES,
useSysNumLines);
useSysNumLines, nsnull, nsGkAtoms::mouseWheel);
break;
case MOUSE_SCROLL_PAGE:
@ -3222,8 +3223,11 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
break;
case MOUSE_SCROLL_PIXELS:
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
false);
{
bool fromLines = msEvent->scrollFlags & nsMouseScrollEvent::kFromLines;
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
false, nsnull, (fromLines ? nsGkAtoms::mouseWheel : nsnull));
}
break;
case MOUSE_SCROLL_HISTORY:

View File

@ -353,7 +353,8 @@ protected:
nsMouseScrollEvent* aMouseEvent,
nsIScrollableFrame::ScrollUnit aScrollQuantity,
bool aAllowScrollSpeedOverride,
nsQueryContentEvent* aQueryEvent = nsnull);
nsQueryContentEvent* aQueryEvent = nsnull,
nsIAtom *aOrigin = nsnull);
void DoScrollHistory(PRInt32 direction);
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);

View File

@ -134,6 +134,7 @@
#include "nsMimeTypes.h"
#include "nsIRequest.h"
#include "nsHtml5TreeOpExecutor.h"
#include "nsHtml5Parser.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1558,6 +1559,7 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
// resetting the document.
mSecurityInfo = securityInfo;
mParserAborted = false;
bool loadAsHtml5 = nsHtml5Module::sEnabled;
if (loadAsHtml5) {
mParser = nsHtml5Module::NewHtml5Parser();
@ -1644,8 +1646,8 @@ nsHTMLDocument::Close()
}
++mWriteLevel;
nsresult rv = mParser->Parse(EmptyString(), nsnull,
GetContentTypeInternal(), true);
nsresult rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
EmptyString(), nsnull, GetContentTypeInternal(), true);
--mWriteLevel;
// XXX Make sure that all the document.written content is
@ -1701,6 +1703,13 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
if (mParserAborted) {
// Hixie says aborting the parser doesn't undefine the insertion point.
// However, since we null out mParser in that case, we track the
// theoretically defined insertion point using mParserAborted.
return NS_OK;
}
nsresult rv = NS_OK;
void *key = GenerateParserKey();
@ -1764,13 +1773,11 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
// since the concatenation of strings costs more than we like. And
// why pay that price when we don't need to?
if (aNewlineTerminate) {
rv = mParser->Parse(aText + new_line,
key, GetContentTypeInternal(),
false);
rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
aText + new_line, key, GetContentTypeInternal(), false);
} else {
rv = mParser->Parse(aText,
key, GetContentTypeInternal(),
false);
rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
aText, key, GetContentTypeInternal(), false);
}
--mWriteLevel;

View File

@ -8348,13 +8348,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
sameExceptHashes && !newHash.IsEmpty());
if (doShortCircuitedLoad) {
// If our load group contains a LOAD_DOCUMENT_URI request with a
// channel which doesn't match our document's channel, cancel it.
//
// That is, a short-circuited load will cancel a non-short-circuited
// load of a different document.
StopOutstandingOtherDocumentLoad();
// Save the current URI; we need it if we fire a hashchange later.
nsCOMPtr<nsIURI> oldURI = mCurrentURI;
@ -8654,47 +8647,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
return rv;
}
// If our load group contains a LOAD_DOCUMENT_URI channel that's not our
// document's channel, cancel it.
void
nsDocShell::StopOutstandingOtherDocumentLoad()
{
nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel();
if (!docChannel || !mLoadGroup) {
return;
}
nsCOMPtr<nsISimpleEnumerator> requests;
mLoadGroup->GetRequests(getter_AddRefs(requests));
if (!requests) {
return;
}
while (true) {
bool hasMoreElements = false;
requests->HasMoreElements(&hasMoreElements);
if (!hasMoreElements) {
break;
}
nsCOMPtr<nsISupports> next;
requests->GetNext(getter_AddRefs(next));
nsCOMPtr<nsIChannel> channel = do_QueryInterface(next);
if (!channel) {
continue;
}
nsLoadFlags flags;
channel->GetLoadFlags(&flags);
// As promised, cancel the channel if it's loading a different document.
if ((flags & nsIChannel::LOAD_DOCUMENT_URI) && channel != docChannel) {
channel->Cancel(NS_BINDING_ABORTED);
}
}
}
nsIPrincipal*
nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
{

View File

@ -672,11 +672,6 @@ protected:
nsresult EnsureCommandHandler();
nsIChannel* GetCurrentDocChannel();
// If our load group contains a LOAD_DOCUMENT_URI channel that's not our
// document's channel, cancel it.
void StopOutstandingOtherDocumentLoad();
protected:
// Override the parent setter from nsDocLoader
virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);

View File

@ -1153,7 +1153,7 @@ Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
mBluetooth = new bluetooth::BluetoothAdapter();
mBluetooth = new bluetooth::BluetoothAdapter(window);
bluetooth = mBluetooth;
}

View File

@ -85,6 +85,7 @@ nsStructuredCloneContainer::InitFromVariant(nsIVariant *aData, JSContext *aCx)
JSAutoRequest ar(aCx);
JSAutoEnterCompartment ac;
NS_ENSURE_STATE(ac.enter(aCx, JS_GetGlobalObject(aCx)));
JS_WrapValue(aCx, &jsData);
nsCxPusher cxPusher;
cxPusher.Push(aCx);

View File

@ -4,13 +4,33 @@
* 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 "BluetoothAdapter.h"
#include "nsDOMClassInfo.h"
#include "nsDOMEvent.h"
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Util.h"
#include <dlfcn.h>
#include "BluetoothAdapter.h"
static void
FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest)
{
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return;
}
mozilla::DebugOnly<nsresult> rv = aResult ?
rs->FireSuccess(aDomRequest, JSVAL_VOID) :
rs->FireError(aDomRequest,
NS_LITERAL_STRING("Bluetooth firmware loading failed"));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed");
}
USING_BLUETOOTH_NAMESPACE
@ -67,11 +87,16 @@ static bool EnsureBluetoothInit() {
class ToggleBtResultTask : public nsRunnable
{
public:
ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
: mResult(result)
ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr,
nsCOMPtr<nsIDOMDOMRequest>& req,
bool enabled,
bool result)
: mResult(result),
mEnabled(enabled)
{
MOZ_ASSERT(!NS_IsMainThread());
mDOMRequest.swap(req);
mAdapterPtr.swap(adapterPtr);
}
@ -79,29 +104,35 @@ class ToggleBtResultTask : public nsRunnable
{
MOZ_ASSERT(NS_IsMainThread());
if (!mResult) {
//TODO:Bug-731361
NS_WARNING("BT firmware loading fails.\n");
// Update bt power status to BluetoothAdapter only if loading bluetooth
// firmware succeeds.
if (mResult) {
mAdapterPtr->SetEnabledInternal(mEnabled);
}
FireEnabled(mResult, mDOMRequest);
//mAdapterPtr must be null before returning to prevent the background
//thread from racing to release it during the destruction of this runnable.
mAdapterPtr->FirePowered();
mAdapterPtr = nsnull;
mDOMRequest = nsnull;
return NS_OK;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
bool mEnabled;
bool mResult;
};
class ToggleBtTask : public nsRunnable
{
public:
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
: mOnOff(onOff),
ToggleBtTask(bool enabled, nsIDOMDOMRequest* req, BluetoothAdapter* adapterPtr)
: mEnabled(enabled),
mDOMRequest(req),
mAdapterPtr(adapterPtr)
{
MOZ_ASSERT(NS_IsMainThread());
@ -111,23 +142,36 @@ class ToggleBtTask : public nsRunnable
{
MOZ_ASSERT(!NS_IsMainThread());
bool result;
#ifdef MOZ_WIDGET_GONK
// Platform specific check for gonk until object is divided in
// different implementations per platform. Linux doesn't require
// bluetooth firmware loading, but code should work otherwise.
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return NS_ERROR_FAILURE;
}
bool result;
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
int isEnabled = sBluedroidFunctions.bt_is_enabled();
//Toggle BT here
if (mOnOff) {
result = sBluedroidFunctions.bt_enable();
if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
result = true;
} else if (isEnabled < 0) {
result = false;
} else if (mEnabled) {
result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
} else {
result = sBluedroidFunctions.bt_disable();
result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
}
#else
result = true;
NS_WARNING("No bluetooth support in this build configuration, faking a success event instead");
#endif
// Create a result thread and pass it to Main Thread,
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, mDOMRequest, mEnabled, result);
if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
@ -137,8 +181,9 @@ class ToggleBtTask : public nsRunnable
}
private:
bool mOnOff;
bool mEnabled;
nsRefPtr<BluetoothAdapter> mAdapterPtr;
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
};
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
@ -147,12 +192,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
@ -163,77 +208,43 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
BluetoothAdapter::BluetoothAdapter()
: mPower(false)
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow *aWindow)
{
BindToOwner(aWindow);
}
NS_IMETHODIMP
BluetoothAdapter::GetPower(bool* aPower)
BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
{
#ifdef MOZ_WIDGET_GONK
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_ERROR("No DOMRequest Service!");
return NS_ERROR_FAILURE;
}
*aPower = sBluedroidFunctions.bt_is_enabled();
#else
*aPower = mPower;
#endif
return NS_OK;
}
NS_IMETHODIMP
BluetoothAdapter::SetPower(bool aPower)
{
#ifdef MOZ_WIDGET_GONK
// Platform specific check for gonk until object is divided in
// different implementations per platform. Linux doesn't require
// bluetooth firmware loading, but code should work otherwise.
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return NS_ERROR_FAILURE;
}
#endif
if (mPower != aPower) {
mPower = aPower;
#ifdef MOZ_WIDGET_GONK
return ToggleBluetoothAsync();
#endif
}
return NS_OK;
}
nsresult
BluetoothAdapter::ToggleBluetoothAsync()
{
nsCOMPtr<nsIDOMDOMRequest> request;
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
NS_ENSURE_SUCCESS(rv, rv);
if (!mToggleBtThread) {
mToggleBtThread = new LazyIdleThread(15000);
}
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
nsresult
BluetoothAdapter::FirePowered()
{
nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false);
rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
rv = event->SetTrusted(true);
NS_ENSURE_SUCCESS(rv, rv);
bool dummy;
rv = DispatchEvent(event, &dummy);
NS_ENSURE_SUCCESS(rv, rv);
request.forget(aDomRequest);
return NS_OK;
}
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)
NS_IMETHODIMP
BluetoothAdapter::GetEnabled(bool* aEnabled)
{
*aEnabled = mEnabled;
return NS_OK;
}

View File

@ -10,6 +10,7 @@
#include "BluetoothCommon.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothAdapter.h"
#include "nsIDOMDOMRequest.h"
class nsIEventTarget;
@ -27,19 +28,19 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
BluetoothAdapter();
BluetoothAdapter(nsPIDOMWindow*);
nsresult FirePowered();
inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
protected:
bool mPower;
bool mEnabled;
NS_DECL_EVENT_HANDLER(powered)
NS_DECL_EVENT_HANDLER(enabled)
private:
nsCOMPtr<nsIEventTarget> mToggleBtThread;
nsresult ToggleBluetoothAsync();
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -6,12 +6,13 @@
#include "nsIDOMEventTarget.idl"
interface nsIDOMDOMRequest;
interface nsIDOMEventListener;
[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
[scriptable, builtinclass, uuid(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)]
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
{
attribute boolean power;
readonly attribute bool enabled;
attribute nsIDOMEventListener onpowered;
nsIDOMDOMRequest setEnabled(in boolean enabled);
};

View File

@ -344,6 +344,13 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange)
DOMCI_DATA(IDBKeyRange, IDBKeyRange)
IDBKeyRange::~IDBKeyRange()
{
if (mRooted) {
NS_DROP_JS_OBJECTS(this, IDBKeyRange);
}
}
NS_IMETHODIMP
IDBKeyRange::GetLower(JSContext* aCx,
jsval* aLower)

View File

@ -170,7 +170,7 @@ public:
}
protected:
~IDBKeyRange() { }
~IDBKeyRange();
Key mLower;
Key mUpper;

View File

@ -1318,8 +1318,6 @@ nsDOMStorage::nsDOMStorage()
: mStorageType(nsPIDOMStorage::Unknown)
, mEventBroadcaster(nsnull)
{
mSecurityChecker = this;
if (XRE_GetProcessType() != GeckoProcessType_Default)
mStorageImpl = new StorageChild(this);
else
@ -1328,10 +1326,9 @@ nsDOMStorage::nsDOMStorage()
nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
: mStorageType(aThat.mStorageType)
, mPrincipal(aThat.mPrincipal)
, mEventBroadcaster(nsnull)
{
mSecurityChecker = this;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
StorageChild* other = static_cast<StorageChild*>(aThat.mStorageImpl.get());
mStorageImpl = new StorageChild(this, *other);
@ -1382,6 +1379,7 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &
NS_ENSURE_SUCCESS(rv, rv);
mDocumentURI = aDocumentURI;
mPrincipal = aPrincipal;
mStorageType = SessionStorage;
@ -1397,6 +1395,7 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD
NS_ENSURE_SUCCESS(rv, rv);
mDocumentURI = aDocumentURI;
mPrincipal = aPrincipal;
mStorageType = LocalStorage;
@ -1495,8 +1494,7 @@ nsDOMStorage::CacheStoragePermissions()
nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
NS_ENSURE_SUCCESS(rv, false);
NS_ASSERTION(mSecurityChecker, "Has non-null mSecurityChecker");
return mSecurityChecker->CanAccess(subjectPrincipal);
return CanAccess(subjectPrincipal);
}
// static
@ -1729,17 +1727,17 @@ nsDOMStorage::CanAccessSystem(nsIPrincipal *aPrincipal)
bool
nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
{
// Allow C++/system callers to access the storage
if (CanAccessSystem(aPrincipal))
// Allow C++ callers to access the storage
if (!aPrincipal)
return true;
nsCAutoString domain;
nsCOMPtr<nsIURI> unused;
nsresult rv = GetPrincipalURIAndHost(aPrincipal,
getter_AddRefs(unused), domain);
NS_ENSURE_SUCCESS(rv, false);
// Allow more powerful principals (e.g. system) to access the storage
bool subsumes;
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
if (NS_FAILED(rv))
return false;
return domain.Equals(mStorageImpl->mDomain);
return subsumes;
}
nsPIDOMStorage::nsDOMStorageType
@ -1797,7 +1795,6 @@ nsDOMStorage2::nsDOMStorage2()
nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat)
{
mStorage = new nsDOMStorage(*aThat.mStorage.get());
mStorage->mSecurityChecker = mStorage;
mPrincipal = aThat.mPrincipal;
}
@ -1808,7 +1805,6 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring
if (!mStorage)
return NS_ERROR_OUT_OF_MEMORY;
mStorage->mSecurityChecker = this;
mPrincipal = aPrincipal;
mDocumentURI = aDocumentURI;
@ -1822,7 +1818,6 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &a
if (!mStorage)
return NS_ERROR_OUT_OF_MEMORY;
mStorage->mSecurityChecker = this;
mPrincipal = aPrincipal;
mDocumentURI = aDocumentURI;
@ -1892,20 +1887,7 @@ nsDOMStorage2::Principal()
bool
nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
{
if (mStorage->mSecurityChecker != this)
return mStorage->mSecurityChecker->CanAccess(aPrincipal);
// Allow C++ callers to access the storage
if (!aPrincipal)
return true;
// Allow more powerful principals (e.g. system) to access the storage
bool subsumes;
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
if (NS_FAILED(rv))
return false;
return subsumes;
return mStorage->CanAccess(aPrincipal);
}
nsPIDOMStorage::nsDOMStorageType

View File

@ -419,7 +419,7 @@ public:
nsDOMStorageType mStorageType;
friend class nsIDOMStorage2;
nsPIDOMStorage* mSecurityChecker;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsPIDOMStorage* mEventBroadcaster;
};

View File

@ -8,7 +8,7 @@ function runAJAXTest() {
var test = AJAXtests.shift();
var testframe = document.getElementById("testframe");
setTimeout(function() { testframe.src = test; }, 0);
testframe.src = test;
}
function onManifestLoad(manifest) {

View File

@ -69,7 +69,7 @@ DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
inline
bool
EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, char* aFunctionName)
EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
{
JSClass* classPtr = JS_GetClass(aObj);
if (ClassIsWorker(classPtr) || ClassIsWorkerGlobalScope(classPtr) ||

View File

@ -3164,6 +3164,8 @@ WorkerPrivate::NotifyFeatures(JSContext* aCx, Status aStatus)
void
WorkerPrivate::CancelAllTimeouts(JSContext* aCx)
{
AssertIsOnWorkerThread();
if (mTimerRunning) {
NS_ASSERTION(mTimer, "Huh?!");
NS_ASSERTION(!mTimeouts.IsEmpty(), "Huh?!");
@ -3176,13 +3178,19 @@ WorkerPrivate::CancelAllTimeouts(JSContext* aCx)
mTimeouts[index]->mCanceled = true;
}
RunExpiredTimeouts(aCx);
if (!RunExpiredTimeouts(aCx)) {
JS_ReportPendingException(aCx);
}
mTimer = nsnull;
mTimerRunning = false;
}
else {
#ifdef DEBUG
else if (!mRunningExpiredTimeouts) {
NS_ASSERTION(mTimeouts.IsEmpty(), "Huh?!");
}
#endif
mTimer = nsnull;
}
PRUint32
@ -3511,8 +3519,15 @@ WorkerPrivate::SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp,
currentStatus = mStatus;
}
if (currentStatus > Running) {
// It's a script bug if setTimeout/setInterval are called from a close handler
// so throw an exception.
if (currentStatus == Closing) {
JS_ReportError(aCx, "Cannot schedule timeouts from the close handler!");
}
// If the worker is trying to call setTimeout/setInterval and the parent
// thread has initiated the close process then just silently fail.
if (currentStatus >= Closing) {
return false;
}
@ -3655,6 +3670,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
return true;
}
NS_ASSERTION(mTimer, "Must have a timer!");
NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!");
bool retval = true;
@ -3719,12 +3735,16 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
}
}
NS_ASSERTION(mRunningExpiredTimeouts, "Someone changed this!");
// Reschedule intervals.
if (info->mIsInterval) {
if (info->mIsInterval && !info->mCanceled) {
PRUint32 timeoutIndex = mTimeouts.IndexOf(info);
NS_ASSERTION(timeoutIndex != PRUint32(-1),
"Should still be in the main list!");
// This is nasty but we have to keep the old nsAutoPtr from deleting the
// info we're about to re-add.
mTimeouts[timeoutIndex].forget();
mTimeouts.RemoveElementAt(timeoutIndex);
@ -3755,8 +3775,8 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
}
}
// Signal the parent that we're no longer using timeouts or reschedule the
// timer.
// Either signal the parent that we're no longer using timeouts or reschedule
// the timer.
if (mTimeouts.IsEmpty()) {
if (!ModifyBusyCountFromWorker(aCx, false)) {
retval = false;

View File

@ -56,6 +56,8 @@ _TEST_FILES = \
test_atob.html \
atob_worker.js \
test_blobWorkers.html \
test_clearTimeouts.html \
clearTimeouts_worker.js \
test_close.html \
close_worker.js \
test_closeOnGC.html \

View File

@ -0,0 +1,12 @@
var count = 0;
function timerFunction() {
if (++count == 30) {
close();
postMessage("ready");
while (true) { }
}
}
for (var i = 0; i < 10; i++) {
setInterval(timerFunction, 500);
}

View File

@ -0,0 +1,30 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for DOM Worker Threads</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
new Worker("clearTimeouts_worker.js").onmessage = function(event) {
event.target.terminate();
is(event.data, "ready", "Correct message");
setTimeout(function() { SimpleTest.finish(); }, 1000);
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

View File

@ -65,7 +65,6 @@ _TEST_FILES = \
test_bug645914.html \
test_bug681229.html \
test_bug692520.html \
test_bug717147.html \
test_dom_input_event_on_texteditor.html \
$(NULL)

View File

@ -1,99 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717147
-->
<head>
<title>Test for Bug 717147</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717147">Mozilla Bug 717147</a>
<p id="display"></p>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="initValue"><input type="submit">
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 717147 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
formTarget.addEventListener("load", function() {
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
setTimeout(function() {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, listener);
newInput.value = "";
newInput.focus();
synthesizeComposition({ type: "compositionstart" });
synthesizeComposition({ type: "compositionupdate", data: "f" });
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
});
hitEventLoop(function() {
ok(!popupShown, "Popup must not be opened during composition");
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: "f" });
hitEventLoop(function () {
ok(popupShown, "Popup must be opened after compositionend");
SpecialPowers.removeAutoCompletePopupEventListener(window, listener);
SimpleTest.finish();
}, 100);
}, 100);
}, 0);
}, false);
initValue.focus();
initValue.value = "foo";
synthesizeKey("VK_ENTER", {});
});
function hitEventLoop(func, times) {
if (times > 0) {
setTimeout(hitEventLoop, 0, func, times - 1);
} else {
setTimeout(func, 0);
}
}
</script>
</pre>
</body>
</html>

View File

@ -55,13 +55,13 @@
#include "nsTextFragment.h"
#include "nsString.h"
#include "nsIAtom.h"
#include "nsParserCIID.h"
#include "nsServiceManagerUtils.h"
#include "nsUnicharUtils.h"
#include "nsIDOMElement.h"
#include "nsIWordBreaker.h"
#include "nsCRT.h"
#include "nsRange.h"
#include "nsContentUtils.h"
// Yikes! Casting a char to unichar can fill with ones!
#define CHAR_TO_UNICHAR(c) ((PRUnichar)(const unsigned char)c)
@ -457,17 +457,6 @@ NS_NewFindContentIterator(bool aFindBackward,
}
// --------------------------------------------------------------------
// Sure would be nice if we could just get these from somewhere else!
PRInt32 nsFind::sInstanceCount = 0;
nsIAtom* nsFind::sImgAtom = nsnull;
nsIAtom* nsFind::sHRAtom = nsnull;
nsIAtom* nsFind::sScriptAtom = nsnull;
nsIAtom* nsFind::sNoframesAtom = nsnull;
nsIAtom* nsFind::sSelectAtom = nsnull;
nsIAtom* nsFind::sTextareaAtom = nsnull;
nsIAtom* nsFind::sThAtom = nsnull;
nsIAtom* nsFind::sTdAtom = nsnull;
NS_IMPL_ISUPPORTS1(nsFind, nsIFind)
nsFind::nsFind()
@ -475,35 +464,10 @@ nsFind::nsFind()
, mCaseSensitive(false)
, mIterOffset(0)
{
// Initialize the atoms if they aren't already:
if (sInstanceCount <= 0)
{
sImgAtom = NS_NewAtom("img");
sHRAtom = NS_NewAtom("hr");
sScriptAtom = NS_NewAtom("script");
sNoframesAtom = NS_NewAtom("noframes");
sSelectAtom = NS_NewAtom("select");
sTextareaAtom = NS_NewAtom("textarea");
sThAtom = NS_NewAtom("th");
sTdAtom = NS_NewAtom("td");
}
++sInstanceCount;
}
nsFind::~nsFind()
{
if (sInstanceCount <= 1)
{
NS_IF_RELEASE(sImgAtom);
NS_IF_RELEASE(sHRAtom);
NS_IF_RELEASE(sScriptAtom);
NS_IF_RELEASE(sNoframesAtom);
NS_IF_RELEASE(sSelectAtom);
NS_IF_RELEASE(sTextareaAtom);
NS_IF_RELEASE(sThAtom);
NS_IF_RELEASE(sTdAtom);
}
--sInstanceCount;
}
#ifdef DEBUG_FIND
@ -780,21 +744,13 @@ bool nsFind::IsBlockNode(nsIContent* aContent)
nsIAtom *atom = aContent->Tag();
if (atom == sImgAtom ||
atom == sHRAtom ||
atom == sThAtom ||
atom == sTdAtom)
if (atom == nsGkAtoms::img ||
atom == nsGkAtoms::hr ||
atom == nsGkAtoms::th ||
atom == nsGkAtoms::td)
return true;
if (!mParserService) {
mParserService = do_GetService(NS_PARSERSERVICE_CONTRACTID);
if (!mParserService)
return false;
}
bool isBlock = false;
mParserService->IsBlock(mParserService->HTMLAtomTagToId(atom), isBlock);
return isBlock;
return nsContentUtils::IsHTMLBlock(atom);
}
bool nsFind::IsTextNode(nsIDOMNode* aNode)
@ -849,9 +805,9 @@ bool nsFind::SkipNode(nsIContent* aContent)
if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
(content->IsHTML() &&
(atom == sScriptAtom ||
atom == sNoframesAtom ||
atom == sSelectAtom)))
(atom == nsGkAtoms::script ||
atom == nsGkAtoms::noframes ||
atom == nsGkAtoms::select)))
{
#ifdef DEBUG_FIND
printf("Skipping node: ");

View File

@ -45,7 +45,6 @@
#include "nsIDOMNode.h"
#include "nsIDOMRange.h"
#include "nsIContentIterator.h"
#include "nsIParserService.h"
#include "nsIWordBreaker.h"
class nsIAtom;
@ -70,26 +69,12 @@ public:
static already_AddRefed<nsIDOMRange> CreateRange();
protected:
static PRInt32 sInstanceCount;
// HTML tags we treat specially
static nsIAtom* sImgAtom;
static nsIAtom* sHRAtom;
// Nodes we skip
static nsIAtom* sScriptAtom;
static nsIAtom* sNoframesAtom;
static nsIAtom* sSelectAtom;
static nsIAtom* sTextareaAtom;
static nsIAtom* sThAtom;
static nsIAtom* sTdAtom;
// Parameters set from the interface:
//nsCOMPtr<nsIDOMRange> mRange; // search only in this range
bool mFindBackward;
bool mCaseSensitive;
nsCOMPtr<nsIWordBreaker> mWordBreaker;
nsCOMPtr<nsIParserService> mParserService;
PRInt32 mIterOffset;
nsCOMPtr<nsIDOMNode> mIterNode;

View File

@ -50,6 +50,8 @@ EXPORTS = \
gfx3DMatrix.h \
gfxASurface.h \
gfxAlphaRecovery.h \
gfxAtomList.h \
gfxAtoms.h \
gfxBlur.h \
gfxCachedTempSurface.h \
gfxColor.h \

View File

@ -95,3 +95,9 @@ GFX_ATOM(x_symbol, "x-symbol")
// referenced in all.js
GFX_ATOM(x_user_def, "x-user-def")
// additional languages that use Turkish-style case transformation
GFX_ATOM(az, "az")
GFX_ATOM(ba, "ba")
GFX_ATOM(crh, "crh")
GFX_ATOM(tt, "tt")

View File

@ -249,6 +249,23 @@ gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName)
aLocalizedName = nsDependentString(famName.Elements());
}
void
gfxDWriteFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
gfxFontFamily::SizeOfExcludingThis(aMallocSizeOf, aSizes);
// TODO:
// This doesn't currently account for |mDWFamily|
}
void
gfxDWriteFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
////////////////////////////////////////////////////////////////////////////////
// gfxDWriteFontEntry
@ -377,7 +394,8 @@ gfxDWriteFontEntry::ReadCMAP()
unicodeFont, symbolFont);
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
@ -424,7 +442,8 @@ gfxDWriteFontEntry::ReadCMAP()
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
@ -544,6 +563,23 @@ gfxDWriteFontEntry::IsCJKFont()
return mIsCJK;
}
void
gfxDWriteFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
// TODO:
// This doesn't currently account for the |mFont| and |mFontFile| members
}
void
gfxDWriteFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
////////////////////////////////////////////////////////////////////////////////
// gfxDWriteFontList
@ -587,7 +623,6 @@ gfxFontEntry *
gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
const nsAString& aFullname)
{
bool found;
gfxFontEntry *lookup;
// initialize name lookup tables if needed
@ -596,8 +631,8 @@ gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
}
// lookup in name lookup tables, return null if not found
if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
!(lookup = mFullnames.GetWeak(aFullname, &found)))
if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
!(lookup = mFullnames.GetWeak(aFullname)))
{
return nsnull;
}
@ -1182,8 +1217,8 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName,
nsAutoString keyName(aFontName);
BuildKeyNameFromFontName(keyName);
nsRefPtr<gfxFontFamily> ff;
if (mFontSubstitutes.Get(keyName, &ff)) {
gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
if (ff) {
aResolvedFontName = ff->Name();
return true;
}
@ -1195,6 +1230,32 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName,
return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName);
}
void
gfxDWriteFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
aSizes->mFontListSize +=
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
aMallocSizeOf);
aSizes->mFontListSize +=
mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
aSizes->mFontListSize +=
mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
}
void
gfxDWriteFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
static nsresult GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName)
{
HRESULT hr;

View File

@ -79,6 +79,11 @@ public:
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
/** This font family's directwrite fontfamily object */
nsRefPtr<IDWriteFontFamily> mDWFamily;
@ -179,6 +184,11 @@ public:
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
bool GetForceGDIClassic() { return mForceGDIClassic; }
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
friend class gfxDWriteFont;
friend class gfxDWriteFontList;
@ -380,6 +390,11 @@ public:
gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; }
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
private:
friend class gfxDWriteFontFamily;
@ -401,7 +416,7 @@ private:
*/
nsTArray<nsString> mNonExistingFonts;
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
/**
* Table of font substitutes, we grab this from the registry to get

View File

@ -389,6 +389,23 @@ FT2FontEntry::GetFontTable(PRUint32 aTableTag,
return NS_OK;
}
void
FT2FontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
aSizes->mFontListSize +=
mFilename.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
void
FT2FontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/*
* FT2FontFamily
* A standard gfxFontFamily; just adds a method used to support sending

View File

@ -102,6 +102,11 @@ public:
nsresult ReadCMAP();
nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
FT_Face mFTFace;
cairo_font_face_t *mFontFace;

View File

@ -272,6 +272,13 @@ public:
mHashEntry = nsnull;
}
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
return mTableData.SizeOfExcludingThis(aMallocSizeOf);
}
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
private:
// The font table data block, owned (via adoption)
FallibleTArray<PRUint8> mTableData;
@ -401,6 +408,46 @@ gfxFontEntry::CheckForGraphiteTables()
}
#endif
/* static */ size_t
gfxFontEntry::FontTableHashEntry::SizeOfEntryExcludingThis
(FontTableHashEntry *aEntry,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
if (aEntry->mBlob) {
sizes->mFontTableCacheSize += aMallocSizeOf(aEntry->mBlob);
}
if (aEntry->mSharedBlobData) {
sizes->mFontTableCacheSize +=
aEntry->mSharedBlobData->SizeOfIncludingThis(aMallocSizeOf);
}
// the size of the table is recorded in the FontListSizes record,
// so we return 0 here for the function result
return 0;
}
void
gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontTableCacheSize +=
mFontTableCache.SizeOfExcludingThis(
FontTableHashEntry::SizeOfEntryExcludingThis,
aMallocSizeOf, aSizes);
}
void
gfxFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
//////////////////////////////////////////////////////////////////////////////
//
// class gfxFontFamily
@ -975,6 +1022,32 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName)
return nsnull;
}
void
gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize +=
mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontListSize +=
mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
for (PRUint32 i = 0; i < mAvailableFonts.Length(); ++i) {
gfxFontEntry *fe = mAvailableFonts[i];
if (fe) {
fe->SizeOfIncludingThis(aMallocSizeOf, aSizes);
}
}
}
void
gfxFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/*
* gfxFontCache - global cache of gfxFont instances.
* Expires unused fonts after a short interval;

View File

@ -91,6 +91,8 @@ struct THEBES_API gfxFontFeature {
// to features that select among multiple alternatives
};
struct FontListSizes;
inline bool
operator<(const gfxFontFeature& a, const gfxFontFeature& b)
{
@ -314,6 +316,12 @@ public:
hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag,
FallibleTArray<PRUint8>* aTable);
// For memory reporting
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
nsString mName;
bool mItalic : 1;
@ -468,6 +476,11 @@ private:
void Clear();
static size_t
SizeOfEntryExcludingThis(FontTableHashEntry *aEntry,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg);
private:
static void DeleteFontTableBlobData(void *aBlobData);
// not implemented
@ -634,6 +647,12 @@ public:
// if so set the mIsSimpleFamily flag (defaults to False before we've checked)
void CheckForSimpleFamily();
// For memory reporter
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
// fills in an array with weights of faces that match style,
// returns whether any matching entries found

View File

@ -264,14 +264,18 @@ public:
}
}
PRUint32 GetSize() {
PRUint32 size = 0;
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
if (mBlocks[i])
size += sizeof(Block);
size += sizeof(nsAutoPtr<Block>);
if (mBlocks[i]) {
total += aMallocSizeOf(mBlocks[i]);
}
}
return size;
return total;
}
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
// clear out all blocks in the array

View File

@ -246,7 +246,8 @@ GDIFontEntry::ReadCMAP()
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
@ -459,6 +460,14 @@ GDIFontEntry::CreateFontEntry(const nsAString& aName,
return fe;
}
void
GDIFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/***************************************************************
*
* GDIFontFamily
@ -658,7 +667,7 @@ gfxGDIFontList::GetFontSubstitutes()
nsAutoString substituteName;
substituteName.AssignLiteral("Courier");
BuildKeyNameFromFontName(substituteName);
if (!mFontSubstitutes.Get(substituteName)) {
if (!mFontSubstitutes.GetWeak(substituteName)) {
gfxFontFamily *ff;
nsAutoString actualFontName;
actualFontName.AssignLiteral("Courier New");
@ -743,7 +752,6 @@ gfxFontEntry*
gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
const nsAString& aFullname)
{
bool found;
gfxFontEntry *lookup;
// initialize name lookup tables if needed
@ -752,8 +760,8 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
}
// lookup in name lookup tables, return null if not found
if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
!(lookup = mFullnames.GetWeak(aFullname, &found)))
if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
!(lookup = mFullnames.GetWeak(aFullname)))
{
return nsnull;
}
@ -1038,8 +1046,8 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved
nsAutoString keyName(aFontName);
BuildKeyNameFromFontName(keyName);
nsRefPtr<gfxFontFamily> ff;
if (mFontSubstitutes.Get(keyName, &ff)) {
gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
if (ff) {
aResolvedFontName = ff->Name();
return true;
}
@ -1052,3 +1060,27 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved
return false;
}
void
gfxGDIFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
aSizes->mFontListSize +=
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
aMallocSizeOf);
aSizes->mFontListSize +=
mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
aSizes->mFontListSize +=
mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
}
void
gfxGDIFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}

View File

@ -274,6 +274,9 @@ public:
virtual bool TestCharacterMap(PRUint32 aCh);
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
// create a font entry for a font with a given name
static GDIFontEntry* CreateFontEntry(const nsAString& aName,
gfxWindowsFontType aFontType,
@ -347,6 +350,11 @@ public:
virtual bool ResolveFontName(const nsAString& aFontName,
nsAString& aResolvedFontName);
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
private:
friend class gfxWindowsPlatform;
@ -361,7 +369,7 @@ private:
DWORD fontType,
LPARAM lParam);
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
FontTable mFontSubstitutes;
nsTArray<nsString> mNonExistingFonts;

View File

@ -111,6 +111,9 @@ public:
virtual nsresult GetFontTable(PRUint32 aTableTag,
FallibleTArray<PRUint8>& aBuffer);
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
virtual bool HasFontTable(PRUint32 aTableTag);
@ -134,6 +137,9 @@ public:
virtual nsresult GetFontTable(PRUint32 aTableTag,
FallibleTArray<PRUint8>& aBuffer);
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
virtual bool HasFontTable(PRUint32 aTableTag);
};

View File

@ -270,7 +270,7 @@ MacOSFontEntry::ReadCMAP()
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.GetSize()));
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
@ -398,6 +398,14 @@ ATSFontEntry::HasFontTable(PRUint32 aTableTag)
(::ATSFontGetTable(fontRef, aTableTag, 0, 0, 0, &size) == noErr);
}
void
ATSFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/* CGFontEntry - used on Mac OS X 10.6+ */
#pragma mark-
@ -486,6 +494,14 @@ CGFontEntry::HasFontTable(PRUint32 aTableTag)
return true;
}
void
CGFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/* gfxMacFontFamily */
#pragma mark-
@ -811,10 +827,9 @@ gfxMacPlatformFontList::InitSingleFaceList()
#endif
// add only if doesn't exist already
bool found;
gfxFontFamily *familyEntry;
if (!(familyEntry = mFontFamilies.GetWeak(key, &found))) {
familyEntry = new gfxSingleFaceMacFontFamily(familyName);
if (!mFontFamilies.GetWeak(key)) {
gfxFontFamily *familyEntry =
new gfxSingleFaceMacFontFamily(familyName);
familyEntry->AddFontEntry(fontEntry);
familyEntry->SetHasStyles(true);
mFontFamilies.Put(key, familyEntry);

View File

@ -130,6 +130,63 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject,
return NS_OK;
}
NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter)
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf, "font-list")
NS_IMETHODIMP
gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName)
{
aName.AssignLiteral("font-list");
return NS_OK;
}
NS_IMETHODIMP
gfxPlatformFontList::MemoryReporter::CollectReports
(nsIMemoryMultiReporterCallback* aCb,
nsISupports* aClosure)
{
FontListSizes sizes;
sizes.mFontListSize = 0;
sizes.mFontTableCacheSize = 0;
sizes.mCharMapsSize = 0;
gfxPlatformFontList::PlatformFontList()->SizeOfIncludingThis(&FontListMallocSizeOf,
&sizes);
aCb->Callback(EmptyCString(),
NS_LITERAL_CSTRING("explicit/gfx/font-list"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
sizes.mFontListSize,
NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."),
aClosure);
aCb->Callback(EmptyCString(),
NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
sizes.mCharMapsSize,
NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."),
aClosure);
if (sizes.mFontTableCacheSize) {
aCb->Callback(EmptyCString(),
NS_LITERAL_CSTRING("explicit/gfx/font-tables"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
sizes.mFontTableCacheSize,
NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."),
aClosure);
}
return NS_OK;
}
NS_IMETHODIMP
gfxPlatformFontList::MemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
{
// This reporter only measures heap memory.
*aAmount = 0;
return NS_OK;
}
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
: mNeedFullnamePostscriptNames(aNeedFullnamePostscriptNames),
@ -184,6 +241,8 @@ gfxPlatformFontList::InitFontList()
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
NS_RegisterMemoryMultiReporter(new MemoryReporter);
sPlatformFontList = this;
return NS_OK;
@ -244,12 +303,11 @@ gfxPlatformFontList::PreloadNamesList()
PRUint32 numFonts = preloadFonts.Length();
for (PRUint32 i = 0; i < numFonts; i++) {
bool found;
nsAutoString key;
GenerateFontListKey(preloadFonts[i], key);
// only search canonical names!
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key, &found);
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
if (familyEntry) {
familyEntry->ReadOtherFamilyNames(this);
}
@ -549,18 +607,17 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
{
nsAutoString key;
gfxFontFamily *familyEntry;
bool found;
GenerateFontListKey(aFamily, key);
NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
// lookup in canonical (i.e. English) family name list
if ((familyEntry = mFontFamilies.GetWeak(key, &found))) {
if ((familyEntry = mFontFamilies.GetWeak(key))) {
return familyEntry;
}
// lookup in other family names list (mostly localized names)
if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
return familyEntry;
}
@ -571,7 +628,7 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
// in practice so avoid pulling in names at startup
if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
InitOtherFamilyNames();
if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
return familyEntry;
}
}
@ -608,10 +665,9 @@ void
gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
{
nsAutoString key;
bool found;
GenerateFontListKey(aOtherFamilyName, key);
if (!mOtherFamilyNames.GetWeak(key, &found)) {
if (!mOtherFamilyNames.GetWeak(key)) {
mOtherFamilyNames.Put(key, aFamilyEntry);
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
@ -627,9 +683,7 @@ gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString&
void
gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
{
bool found;
if (!mFullnames.GetWeak(aFullname, &found)) {
if (!mFullnames.GetWeak(aFullname)) {
mFullnames.Put(aFullname, aFontEntry);
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
@ -642,9 +696,7 @@ gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
void
gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName)
{
bool found;
if (!mPostscriptNames.GetWeak(aPostscriptName, &found)) {
if (!mPostscriptNames.GetWeak(aPostscriptName)) {
mPostscriptNames.Put(aPostscriptName, aFontEntry);
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
@ -714,3 +766,111 @@ gfxPlatformFontList::FinishLoader()
mFontFamiliesToLoad.Clear();
mNumFamilies = 0;
}
// Support for memory reporting
static size_t
SizeOfFamilyEntryExcludingThis(const nsAString& aKey,
const nsRefPtr<gfxFontFamily>& aFamily,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
aFamily->SizeOfExcludingThis(aMallocSizeOf, sizes);
sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
// we return zero here because the measurements have been added directly
// to the relevant fields of the FontListSizes record
return 0;
}
// this is also used by subclasses that hold additional hashes of family names
/*static*/ size_t
gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
(const nsAString& aKey,
const nsRefPtr<gfxFontFamily>& aFamily,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
// we don't count the size of the family here, because this is an *extra*
// reference to a family that will have already been counted in the main list
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
static size_t
SizeOfFontNameEntryExcludingThis(const nsAString& aKey,
const nsRefPtr<gfxFontEntry>& aFont,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
// the font itself is counted by its owning family; here we only care about
// the name stored in the hashtable key
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
static size_t
SizeOfPrefFontEntryExcludingThis
(const PRUint32& aKey,
const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
// again, we only care about the size of the array itself; we don't follow
// the refPtrs stored in it, because they point to entries already owned
// and accounted-for by the main font list
return aList.SizeOfExcludingThis(aMallocSizeOf);
}
static size_t
SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg)
{
return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
void
gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize +=
mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
aMallocSizeOf, aSizes);
aSizes->mFontListSize +=
mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
aMallocSizeOf);
if (mNeedFullnamePostscriptNames) {
aSizes->mFontListSize +=
mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
aMallocSizeOf);
aSizes->mFontListSize +=
mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
aMallocSizeOf);
}
aSizes->mFontListSize +=
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontListSize +=
mReplacementCharFallbackFamily.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
aSizes->mFontListSize +=
mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontListSize +=
mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
aMallocSizeOf);
aSizes->mFontListSize +=
mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
aMallocSizeOf);
}
void
gfxPlatformFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}

View File

@ -47,6 +47,7 @@
#include "gfxFont.h"
#include "gfxPlatform.h"
#include "nsIMemoryReporter.h"
#include "mozilla/FunctionTimer.h"
// gfxPlatformFontList is an abstract class for the global font list on the system;
@ -57,6 +58,14 @@
// Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms.
struct FontListSizes {
PRUint32 mFontListSize; // size of the font list and dependent objects
// (font family and face names, etc), but NOT
// including the font table cache and the cmaps
PRUint32 mFontTableCacheSize; // memory used for the gfxFontEntry table caches
PRUint32 mCharMapsSize; // memory used for cmap coverage info
};
class gfxPlatformFontList : protected gfxFontInfoLoader
{
public:
@ -141,7 +150,20 @@ public:
// (platforms may override, eg Mac)
virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
FontListSizes* aSizes) const;
protected:
class MemoryReporter
: public nsIMemoryMultiReporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORYMULTIREPORTER
};
gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
static gfxPlatformFontList *sPlatformFontList;
@ -200,6 +222,13 @@ protected:
virtual bool RunLoader();
virtual void FinishLoader();
// used by memory reporter to accumulate sizes of family names in the hash
static size_t
SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey,
const nsRefPtr<gfxFontFamily>& aFamily,
nsMallocSizeOfFun aMallocSizeOf,
void* aUserArg);
// canonical family name ==> family entry (unique, one name per family entry)
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mFontFamilies;

View File

@ -88,6 +88,12 @@ using namespace mozilla::gfx;
#include "nsMemory.h"
#endif
/*
* Required headers are not available in the current consumer preview Win8
* dev kit, disabling for now.
*/
#undef MOZ_WINSDK_TARGETVER
/**
* XXX below should be >= MOZ_NTDDI_WIN8 or such which is not defined yet
*/

View File

@ -1,265 +1,265 @@
aa.accept = false
ab.accept = true
ae.accept = false
af.accept = true
ak.accept = false
am.accept = true
an.accept = true
ar.accept = true
ar-ae.accept = true
ar-bh.accept = true
ar-dz.accept = true
ar-eg.accept = true
ar-iq.accept = true
ar-jo.accept = true
ar-kw.accept = true
ar-lb.accept = true
ar-ly.accept = true
ar-ma.accept = true
ar-om.accept = true
ar-qa.accept = true
ar-sa.accept = true
ar-sy.accept = true
ar-tn.accept = true
ar-ye.accept = true
as.accept = true
ast.accept = true
av.accept = false
ay.accept = true
az.accept = true
ba.accept = false
be.accept = true
bg.accept = true
bh.accept = false
bi.accept = false
bm.accept = false
bn.accept = true
bo.accept = true
br.accept = true
bs.accept = true
ca.accept = true
ce.accept = true
ch.accept = true
co.accept = true
cr.accept = true
cs.accept = true
cu.accept = false
cv.accept = true
cy.accept = true
da.accept = true
de.accept = true
de-at.accept = true
de-ch.accept = true
de-de.accept = true
de-li.accept = true
de-lu.accept = true
dv.accept = false
dz.accept = true
ee.accept = false
el.accept = true
en.accept = true
en-au.accept = true
en-bz.accept = true
en-ca.accept = true
en-gb.accept = true
en-ie.accept = true
en-jm.accept = true
en-nz.accept = true
en-ph.accept = true
en-tt.accept = true
en-us.accept = true
en-za.accept = true
en-zw.accept = true
eo.accept = true
es.accept = true
es-ar.accept = true
es-bo.accept = true
es-cl.accept = true
es-co.accept = true
es-cr.accept = true
es-do.accept = true
es-ec.accept = true
es-es.accept = true
es-gt.accept = true
es-hn.accept = true
es-mx.accept = true
es-ni.accept = true
es-pa.accept = true
es-pe.accept = true
es-pr.accept = true
es-py.accept = true
es-sv.accept = true
es-uy.accept = true
es-ve.accept = true
et.accept = true
eu.accept = true
fa.accept = true
fa-ir.accept = true
ff.accept = false
fi.accept = true
fj.accept = true
fo.accept = true
fr.accept = true
fr-be.accept = true
fr-ca.accept = true
fr-ch.accept = true
fr-fr.accept = true
fr-lu.accept = true
fr-mc.accept = true
fur.accept = true
fy.accept = true
ga.accept = true
gd.accept = true
gl.accept = true
gn.accept = true
gu.accept = true
gv.accept = true
ha.accept = false
he.accept = true
hi.accept = true
ho.accept = false
hsb.accept = true
hr.accept = true
ht.accept = true
hu.accept = true
hy.accept = true
hz.accept = false
ia.accept = true
id.accept = true
ie.accept = true
ig.accept = false
ii.accept = false
ik.accept = false
io.accept = false
is.accept = true
it.accept = true
it-ch.accept = true
iu.accept = true
ja.accept = true
jv.accept = false
ka.accept = true
kg.accept = false
ki.accept = false
kk.accept = true
kl.accept = true
km.accept = true
kn.accept = true
ko.accept = true
ko-kp.accept = true
ko-kr.accept = true
kok.accept = true
kr.accept = false
ks.accept = true
ku.accept = true
kv.accept = false
kw.accept = false
ky.accept = true
la.accept = true
lb.accept = true
lg.accept = false
li.accept = false
ln.accept = true
lo.accept = false
lt.accept = true
lu.accept = false
lv.accept = true
mg.accept = true
mh.accept = true
mi.accept = true
mk.accept = false
mk-mk.accept = true
ml.accept = true
mn.accept = true
mr.accept = true
ms.accept = true
mt.accept = true
my.accept = true
na.accept = true
nb.accept = true
nd.accept = true
ne.accept = true
ng.accept = true
nl.accept = true
nl-be.accept = true
nn.accept = true
no.accept = true
nr.accept = true
nso.accept = true
nv.accept = true
ny.accept = true
oc.accept = true
oj.accept = false
om.accept = true
or.accept = true
os.accept = false
pa.accept = true
pa-in.accept = true
pa-pk.accept = true
pi.accept = false
pl.accept = true
ps.accept = true
pt.accept = true
pt-br.accept = true
qu.accept = true
rm.accept = true
rn.accept = true
ro.accept = true
ro-md.accept = true
ro-ro.accept = true
ru.accept = true
ru-md.accept = false
rw.accept = true
sa.accept = true
sc.accept = true
sd.accept = true
sg.accept = true
si.accept = true
sk.accept = true
sl.accept = true
sm.accept = true
so.accept = true
aa.accept = true
ab.accept = true
ae.accept = true
af.accept = true
ak.accept = true
am.accept = true
an.accept = true
ar.accept = true
ar-ae.accept = true
ar-bh.accept = true
ar-dz.accept = true
ar-eg.accept = true
ar-iq.accept = true
ar-jo.accept = true
ar-kw.accept = true
ar-lb.accept = true
ar-ly.accept = true
ar-ma.accept = true
ar-om.accept = true
ar-qa.accept = true
ar-sa.accept = true
ar-sy.accept = true
ar-tn.accept = true
ar-ye.accept = true
as.accept = true
ast.accept = true
av.accept = true
ay.accept = true
az.accept = true
ba.accept = true
be.accept = true
bg.accept = true
bh.accept = true
bi.accept = true
bm.accept = true
bn.accept = true
bo.accept = true
br.accept = true
bs.accept = true
ca.accept = true
ce.accept = true
ch.accept = true
co.accept = true
cr.accept = true
cs.accept = true
cu.accept = true
cv.accept = true
cy.accept = true
da.accept = true
de.accept = true
de-at.accept = true
de-ch.accept = true
de-de.accept = true
de-li.accept = true
de-lu.accept = true
dv.accept = true
dz.accept = true
ee.accept = true
el.accept = true
en.accept = true
en-au.accept = true
en-bz.accept = true
en-ca.accept = true
en-gb.accept = true
en-ie.accept = true
en-jm.accept = true
en-nz.accept = true
en-ph.accept = true
en-tt.accept = true
en-us.accept = true
en-za.accept = true
en-zw.accept = true
eo.accept = true
es.accept = true
es-ar.accept = true
es-bo.accept = true
es-cl.accept = true
es-co.accept = true
es-cr.accept = true
es-do.accept = true
es-ec.accept = true
es-es.accept = true
es-gt.accept = true
es-hn.accept = true
es-mx.accept = true
es-ni.accept = true
es-pa.accept = true
es-pe.accept = true
es-pr.accept = true
es-py.accept = true
es-sv.accept = true
es-uy.accept = true
es-ve.accept = true
et.accept = true
eu.accept = true
fa.accept = true
fa-ir.accept = true
ff.accept = true
fi.accept = true
fj.accept = true
fo.accept = true
fr.accept = true
fr-be.accept = true
fr-ca.accept = true
fr-ch.accept = true
fr-fr.accept = true
fr-lu.accept = true
fr-mc.accept = true
fur.accept = true
fy.accept = true
ga.accept = true
gd.accept = true
gl.accept = true
gn.accept = true
gu.accept = true
gv.accept = true
ha.accept = true
he.accept = true
hi.accept = true
ho.accept = true
hsb.accept = true
hr.accept = true
ht.accept = true
hu.accept = true
hy.accept = true
hz.accept = true
ia.accept = true
id.accept = true
ie.accept = true
ig.accept = true
ii.accept = true
ik.accept = true
io.accept = true
is.accept = true
it.accept = true
it-ch.accept = true
iu.accept = true
ja.accept = true
jv.accept = true
ka.accept = true
kg.accept = true
ki.accept = true
kk.accept = true
kl.accept = true
km.accept = true
kn.accept = true
ko.accept = true
ko-kp.accept = true
ko-kr.accept = true
kok.accept = true
kr.accept = true
ks.accept = true
ku.accept = true
kv.accept = true
kw.accept = true
ky.accept = true
la.accept = true
lb.accept = true
lg.accept = true
li.accept = true
ln.accept = true
lo.accept = true
lt.accept = true
lu.accept = true
lv.accept = true
mg.accept = true
mh.accept = true
mi.accept = true
mk.accept = true
mk-mk.accept = true
ml.accept = true
mn.accept = true
mr.accept = true
ms.accept = true
mt.accept = true
my.accept = true
na.accept = true
nb.accept = true
nd.accept = true
ne.accept = true
ng.accept = true
nl.accept = true
nl-be.accept = true
nn.accept = true
no.accept = true
nr.accept = true
nso.accept = true
nv.accept = true
ny.accept = true
oc.accept = true
oj.accept = true
om.accept = true
or.accept = true
os.accept = true
pa.accept = true
pa-in.accept = true
pa-pk.accept = true
pi.accept = true
pl.accept = true
ps.accept = true
pt.accept = true
pt-br.accept = true
qu.accept = true
rm.accept = true
rn.accept = true
ro.accept = true
ro-md.accept = true
ro-ro.accept = true
ru.accept = true
ru-md.accept = true
rw.accept = true
sa.accept = true
sc.accept = true
sd.accept = true
sg.accept = true
si.accept = true
sk.accept = true
sl.accept = true
sm.accept = true
so.accept = true
son-ml.accept = true
sq.accept = true
sr.accept = true
ss.accept = true
st.accept = true
su.accept = false
sv.accept = true
sv-fi.accept = true
sv-se.accept = true
sw.accept = true
ta.accept = true
te.accept = true
tg.accept = false
th.accept = true
ti.accept = true
tig.accept = true
tk.accept = true
tl.accept = true
tlh.accept = true
tn.accept = true
to.accept = true
tr.accept = true
ts.accept = true
tt.accept = true
tw.accept = false
ty.accept = false
ug.accept = false
uk.accept = true
ur.accept = true
uz.accept = false
ve.accept = true
vi.accept = true
vo.accept = true
wa.accept = true
wo.accept = true
xh.accept = true
yi.accept = true
yo.accept = false
za.accept = false
zh.accept = true
zh-cn.accept = true
zh-hk.accept = true
zh-sg.accept = true
zh-tw.accept = true
zu.accept = true
sq.accept = true
sr.accept = true
ss.accept = true
st.accept = true
su.accept = true
sv.accept = true
sv-fi.accept = true
sv-se.accept = true
sw.accept = true
ta.accept = true
te.accept = true
tg.accept = true
th.accept = true
ti.accept = true
tig.accept = true
tk.accept = true
tl.accept = true
tlh.accept = true
tn.accept = true
to.accept = true
tr.accept = true
ts.accept = true
tt.accept = true
tw.accept = true
ty.accept = true
ug.accept = true
uk.accept = true
ur.accept = true
uz.accept = true
ve.accept = true
vi.accept = true
vo.accept = true
wa.accept = true
wo.accept = true
xh.accept = true
yi.accept = true
yo.accept = true
za.accept = true
zh.accept = true
zh-cn.accept = true
zh-hk.accept = true
zh-sg.accept = true
zh-tw.accept = true
zu.accept = true

View File

@ -967,22 +967,6 @@ EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce)
return EmitIndex32(cx, JSOP_REGEXP, index, bce);
}
static bool
EmitSlotObjectOp(JSContext *cx, JSOp op, unsigned slot, uint32_t index, BytecodeEmitter *bce)
{
JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTOBJECT);
ptrdiff_t off = EmitN(cx, bce, op, SLOTNO_LEN + UINT32_INDEX_LEN);
if (off < 0)
return false;
jsbytecode *pc = bce->code(off);
SET_SLOTNO(pc, slot);
pc += SLOTNO_LEN;
SET_UINT32_INDEX(pc, index);
return true;
}
static bool
EmitArguments(JSContext *cx, BytecodeEmitter *bce)
{
@ -4581,43 +4565,6 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return PopStatementBCE(cx, bce);
}
static bool
SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
{
RootedVarObject parent(cx);
parent = funbox->function()->getParent();
/*
* Replace a boxed function with a new one with a method atom. Methods
* require a function with the extended size finalize kind, which normal
* functions don't have. We don't eagerly allocate functions with the
* expanded size for boxed functions, as most functions are not methods.
*/
JSFunction *fun = js_NewFunction(cx, NULL, NULL,
funbox->function()->nargs,
funbox->function()->flags,
parent,
funbox->function()->atom,
JSFunction::ExtendedFinalizeKind);
if (!fun)
return false;
JSScript *script = funbox->function()->script();
if (script) {
fun->setScript(script);
if (!script->typeSetFunction(cx, fun))
return false;
}
JS_ASSERT(funbox->function()->joinable());
fun->setJoinable();
fun->setMethodAtom(atom);
funbox->object = fun;
return true;
}
static bool
EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
@ -5054,7 +5001,14 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
return false;
}
return EmitSlotObjectOp(cx, JSOP_DEFLOCALFUN, slot, index, bce);
if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
return false;
if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce))
return false;
EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, slot);
if (Emit1(cx, bce, JSOP_POP) < 0)
return false;
}
return true;
@ -5380,23 +5334,6 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
#endif
if (op != JSOP_NOP) {
/*
* Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or
* avoid null closure cloning. Do this only for assignment
* statements that are not completion values wanted by a
* script evaluator, to ensure that the joined function
* can't escape directly.
*/
if (!wantval &&
pn2->isKind(PNK_ASSIGN) &&
pn2->pn_left->isOp(JSOP_SETPROP) &&
pn2->pn_right->isOp(JSOP_LAMBDA) &&
pn2->pn_right->pn_funbox->joinable())
{
if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
return false;
pn2->pn_left->setOp(JSOP_SETMETHOD);
}
if (!EmitTree(cx, bce, pn2))
return false;
if (Emit1(cx, bce, op) < 0)
@ -5903,28 +5840,13 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (!bce->makeAtomIndex(pn3->pn_atom, &index))
return false;
/* Check whether we can optimize to JSOP_INITMETHOD. */
ParseNode *init = pn2->pn_right;
bool lambda = init->isOp(JSOP_LAMBDA);
if (lambda)
++methodInits;
if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) {
/*
* Disable NEWOBJECT on initializers that set __proto__, which has
* a non-standard setter on objects.
*/
if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
obj = NULL;
op = JSOP_INITMETHOD;
if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
return JS_FALSE;
pn2->setOp(op);
} else {
/*
* Disable NEWOBJECT on initializers that set __proto__, which has
* a non-standard setter on objects.
*/
if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
obj = NULL;
op = JSOP_INITPROP;
if (lambda)
++slowMethodInits;
}
op = JSOP_INITPROP;
if (obj) {
JS_ASSERT(!obj->inDictionaryMode());

View File

@ -161,126 +161,127 @@ struct StmtInfo {
#define SET_STATEMENT_TOP(stmt, top) \
((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
#define TCF_COMPILING 0x01 /* TreeContext is BytecodeEmitter */
#define TCF_IN_FUNCTION 0x02 /* parsing inside function body */
#define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */
#define TCF_RETURN_VOID 0x08 /* function has 'return;' */
#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */
#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function may contain a local named arguments */
#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a
parameter name */
#define TCF_FUN_HEAVYWEIGHT 0x200 /* function needs Call object per call */
#define TCF_FUN_IS_GENERATOR 0x400 /* parsed yield statement in function */
#define TCF_FUN_USES_OWN_NAME 0x800 /* named function expression that uses its
own name */
#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */
#define TCF_GENEXP_LAMBDA 0x2000 /* flag lambda from generator expression */
#define TCF_COMPILE_N_GO 0x4000 /* compile-and-go mode of script, can
optimize name references based on scope
chain */
#define TCF_NO_SCRIPT_RVAL 0x8000 /* API caller does not want result value
from global script */
/*
* Set when parsing a declaration-like destructuring pattern. This
* flag causes PrimaryExpr to create PN_NAME parse nodes for variable
* references which are not hooked into any definition's use chain,
* added to any tree context's AtomList, etc. etc. CheckDestructuring
* will do that work later.
*
* The comments atop CheckDestructuring explain the distinction
* between assignment-like and declaration-like destructuring
* patterns, and why they need to be treated differently.
*/
#define TCF_DECL_DESTRUCTURING 0x10000
JS_ENUM_HEADER(TreeContextFlags, uint32_t)
{
/* TreeContext is BytecodeEmitter */
TCF_COMPILING = 0x1,
/*
* This function/global/eval code body contained a Use Strict Directive. Treat
* certain strict warnings as errors, and forbid the use of 'with'. See also
* TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and JSREPORT_STRICT_ERROR.
*/
#define TCF_STRICT_MODE_CODE 0x20000
/* parsing inside function body */
TCF_IN_FUNCTION = 0x2,
/* bits 0x40000 and 0x80000 are unused */
/* function has 'return expr;' */
TCF_RETURN_EXPR = 0x4,
/*
* "Module pattern", i.e., a lambda that is immediately applied and the whole
* of an expression statement.
*/
#define TCF_FUN_MODULE_PATTERN 0x200000
/* function has 'return;' */
TCF_RETURN_VOID = 0x8,
/*
* Flag to prevent a non-escaping function from being optimized into a null
* closure (i.e., a closure that needs only its global object for free variable
* resolution), because this function contains a closure that needs one or more
* scope objects surrounding it (i.e., a Call object for an outer heavyweight
* function). See bug 560234.
*/
#define TCF_FUN_ENTRAINS_SCOPES 0x400000
/* parsing init expr of for; exclude 'in' */
TCF_IN_FOR_INIT = 0x10,
/* The function calls 'eval'. */
#define TCF_FUN_CALLS_EVAL 0x800000
/* function has parameter named arguments */
TCF_FUN_PARAM_ARGUMENTS = 0x20,
/* The function mutates a positional (non-destructuring) parameter. */
#define TCF_FUN_MUTATES_PARAMETER 0x1000000
/* function may contain a local named arguments */
TCF_FUN_LOCAL_ARGUMENTS = 0x40,
/*
* Compiling an eval() script.
*/
#define TCF_COMPILE_FOR_EVAL 0x2000000
/* function uses arguments except as a parameter name */
TCF_FUN_USES_ARGUMENTS = 0x80,
/*
* The function or a function that encloses it may define new local names
* at runtime through means other than calling eval.
*/
#define TCF_FUN_MIGHT_ALIAS_LOCALS 0x4000000
/* function needs Call object per call */
TCF_FUN_HEAVYWEIGHT = 0x100,
/*
* The script contains singleton initialiser JSOP_OBJECT.
*/
#define TCF_HAS_SINGLETONS 0x8000000
/* parsed yield statement in function */
TCF_FUN_IS_GENERATOR = 0x200,
/*
* Some enclosing scope is a with-statement or E4X filter-expression.
*/
#define TCF_IN_WITH 0x10000000
/* named function expression that uses its own name */
TCF_FUN_USES_OWN_NAME = 0x400,
/*
* This function does something that can extend the set of bindings in its
* call objects --- it does a direct eval in non-strict code, or includes a
* function statement (as opposed to a function definition).
*
* This flag is *not* inherited by enclosed or enclosing functions; it
* applies only to the function in whose flags it appears.
*/
#define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000
/* block contains a function statement */
TCF_HAS_FUNCTION_STMT = 0x800,
/*
* The caller is JS_Compile*Script*.
*/
#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
/* flag lambda from generator expression */
TCF_GENEXP_LAMBDA = 0x1000,
/*
* Flags to check for return; vs. return expr; in a function.
*/
#define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID)
/* script can optimize name references based on scope chain */
TCF_COMPILE_N_GO = 0x2000,
/* API caller does not want result value from global script */
TCF_NO_SCRIPT_RVAL = 0x4000,
/*
* Set when parsing a declaration-like destructuring pattern. This flag
* causes PrimaryExpr to create PN_NAME parse nodes for variable references
* which are not hooked into any definition's use chain, added to any tree
* context's AtomList, etc. etc. CheckDestructuring will do that work
* later.
*
* The comments atop CheckDestructuring explain the distinction between
* assignment-like and declaration-like destructuring patterns, and why
* they need to be treated differently.
*/
TCF_DECL_DESTRUCTURING = 0x8000,
/*
* This function/global/eval code body contained a Use Strict Directive.
* Treat certain strict warnings as errors, and forbid the use of 'with'.
* See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
* JSREPORT_STRICT_ERROR.
*/
TCF_STRICT_MODE_CODE = 0x10000,
/* The function calls 'eval'. */
TCF_FUN_CALLS_EVAL = 0x20000,
/* The function mutates a positional (non-destructuring) parameter. */
TCF_FUN_MUTATES_PARAMETER = 0x40000,
/* Compiling an eval() script. */
TCF_COMPILE_FOR_EVAL = 0x100000,
/*
* The function or a function that encloses it may define new local names
* at runtime through means other than calling eval.
*/
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x200000,
/* The script contains singleton initialiser JSOP_OBJECT. */
TCF_HAS_SINGLETONS = 0x400000,
/* Some enclosing scope is a with-statement or E4X filter-expression. */
TCF_IN_WITH = 0x800000,
/*
* This function does something that can extend the set of bindings in its
* call objects --- it does a direct eval in non-strict code, or includes a
* function statement (as opposed to a function definition).
*
* This flag is *not* inherited by enclosed or enclosing functions; it
* applies only to the function in whose flags it appears.
*/
TCF_FUN_EXTENSIBLE_SCOPE = 0x1000000,
/* The caller is JS_Compile*Script*. */
TCF_NEED_SCRIPT_GLOBAL = 0x2000000
} JS_ENUM_FOOTER(TreeContextFlags);
/* Flags to check for return; vs. return expr; in a function. */
static const uint32_t TCF_RETURN_FLAGS = TCF_RETURN_EXPR | TCF_RETURN_VOID;
/*
* Sticky deoptimization flags to propagate from FunctionBody.
*/
#define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \
TCF_FUN_USES_ARGUMENTS | \
TCF_FUN_PARAM_ARGUMENTS | \
TCF_FUN_LOCAL_ARGUMENTS | \
TCF_FUN_HEAVYWEIGHT | \
TCF_FUN_IS_GENERATOR | \
TCF_FUN_USES_OWN_NAME | \
TCF_FUN_CALLS_EVAL | \
TCF_FUN_MIGHT_ALIAS_LOCALS | \
TCF_FUN_MUTATES_PARAMETER | \
TCF_STRICT_MODE_CODE | \
TCF_FUN_EXTENSIBLE_SCOPE)
static const uint32_t TCF_FUN_FLAGS = TCF_FUN_USES_ARGUMENTS |
TCF_FUN_PARAM_ARGUMENTS |
TCF_FUN_LOCAL_ARGUMENTS |
TCF_FUN_HEAVYWEIGHT |
TCF_FUN_IS_GENERATOR |
TCF_FUN_USES_OWN_NAME |
TCF_FUN_CALLS_EVAL |
TCF_FUN_MIGHT_ALIAS_LOCALS |
TCF_FUN_MUTATES_PARAMETER |
TCF_STRICT_MODE_CODE |
TCF_FUN_EXTENSIBLE_SCOPE;
struct BytecodeEmitter;
@ -443,14 +444,16 @@ struct TreeContext { /* tree context for semantic checks */
flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS));
}
void noteLocalOverwritesArguments() {
flags |= TCF_FUN_LOCAL_ARGUMENTS;
}
void noteArgumentsNameUse(ParseNode *node) {
JS_ASSERT(inFunction());
JS_ASSERT(node->isKind(PNK_NAME));
JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
countArgumentsUse(node);
flags |= TCF_FUN_USES_ARGUMENTS;
if (funbox)
funbox->node->pn_dflags |= PND_FUNARG;
}
/*

View File

@ -108,15 +108,6 @@ ParseNode::clear()
pn_parens = false;
}
bool
FunctionBox::joinable() const
{
return function()->isNullClosure() &&
(tcflags & (TCF_FUN_USES_ARGUMENTS |
TCF_FUN_USES_OWN_NAME |
TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO;
}
bool
FunctionBox::inAnyDynamicScope() const
{

View File

@ -765,15 +765,14 @@ struct ParseNode {
#define PND_GVAR 0x40 /* gvar binding, can't close over
because it could be deleted */
#define PND_PLACEHOLDER 0x80 /* placeholder definition for lexdep */
#define PND_FUNARG 0x100 /* downward or upward funarg usage */
#define PND_BOUND 0x200 /* bound to a stack or global slot */
#define PND_DEOPTIMIZED 0x400 /* former pn_used name node, pn_lexdef
#define PND_BOUND 0x100 /* bound to a stack or global slot */
#define PND_DEOPTIMIZED 0x200 /* former pn_used name node, pn_lexdef
still valid, but this use no longer
optimizable via an upvar opcode */
#define PND_CLOSED 0x800 /* variable is closed over */
#define PND_CLOSED 0x400 /* variable is closed over */
/* Flags to propagate from uses to definition. */
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
/* PN_LIST pn_xflags bits. */
#define PNX_STRCAT 0x01 /* PNK_ADD list has string term */
@ -816,7 +815,6 @@ struct ParseNode {
bool isPlaceholder() const { return test(PND_PLACEHOLDER); }
bool isDeoptimized() const { return test(PND_DEOPTIMIZED); }
bool isAssigned() const { return test(PND_ASSIGNED); }
bool isFunArg() const { return test(PND_FUNARG); }
bool isClosed() const { return test(PND_CLOSED); }
/*
@ -833,9 +831,6 @@ struct ParseNode {
*/
bool isTopLevel() const { return test(PND_TOPLEVEL); }
/* Defined below, see after struct Definition. */
void setFunArg();
void become(ParseNode *pn2);
void clear();
@ -1431,26 +1426,6 @@ void DumpParseTree(ParseNode *pn, int indent = 0);
* When the compiler unwinds from the outermost tc, tc->lexdeps contains the
* definition nodes with use chains for all free variables. These are either
* global variables or reference errors.
*
* We analyze whether a binding is initialized, whether the bound names is ever
* assigned apart from its initializer, and if the bound name definition or use
* is in a direct child of a block. These PND_* flags allow a subset dominance
* computation telling whether an initialized var dominates its uses. An inner
* function using only such outer vars (and formal parameters) can be optimized
* into a flat closure. See JSOP_{GET,CALL}DSLOT.
*
* Another important subset dominance relation: ... { var x = ...; ... x ... }
* where x is not assigned after initialization and not used outside the block.
* This style is common in the absence of 'let'. Even though the var x is not
* at top level, we can tell its initialization dominates all uses cheaply,
* because the above one-pass algorithm sees the definition before any uses,
* and because all uses are contained in the same block as the definition.
*
* We also analyze function uses to flag upward/downward funargs. If a lambda
* post-dominates each of its upvars' sole, inevitable (i.e. not hidden behind
* conditions or within loops or the like) initialization or assignment; then
* we can optimize the lambda as a flat closure (after Chez Scheme's display
* closures).
*/
#define dn_uses pn_link
@ -1528,7 +1503,7 @@ ParseNode::test(unsigned flag) const
{
JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME);
#ifdef DEBUG
if ((flag & (PND_ASSIGNED | PND_FUNARG)) && pn_defn && !(pn_dflags & flag)) {
if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) {
for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) {
JS_ASSERT(!pn->pn_defn);
JS_ASSERT(!(pn->pn_dflags & flag));
@ -1538,25 +1513,6 @@ ParseNode::test(unsigned flag) const
return !!(pn_dflags & flag);
}
inline void
ParseNode::setFunArg()
{
/*
* pn_defn NAND pn_used must be true, per this chart:
*
* pn_defn pn_used
* 0 0 anonymous function used implicitly, e.g. by
* hidden yield in a genexp
* 0 1 a use of a definition or placeholder
* 1 0 a definition or placeholder
* 1 1 error: this case must not be possible
*/
JS_ASSERT(!(pn_defn & pn_used));
if (pn_used)
pn_lexdef->pn_dflags |= PND_FUNARG;
pn_dflags |= PND_FUNARG;
}
inline void
LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc)
{
@ -1598,8 +1554,6 @@ struct FunctionBox : public ObjectBox
JSFunction *function() const { return (JSFunction *) object; }
bool joinable() const;
/*
* True if this function is inside the scope of a with-statement, an E4X
* filter-expression, or a function that uses direct eval.

Some files were not shown because too many files have changed in this diff Show More