Merge m-c to b-s

This commit is contained in:
Kyle Huey 2011-06-30 09:03:22 -07:00
commit 26d60b6f50
198 changed files with 3991 additions and 1305 deletions

View File

@ -1081,7 +1081,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
nsString newName;
accessible->GetName(newName);
NS_ConvertUTF16toUTF8 utf8Name(newName);
if (!utf8Name.Equals(atkObj->name))
if (!atkObj->name || !utf8Name.Equals(atkObj->name))
atk_object_set_name(atkObj, utf8Name.get());
break;

View File

@ -635,6 +635,9 @@ nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
nsIAccessible **aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
if (!aNode)
return NS_OK;
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
NS_IF_ADDREF(*aAccessible = GetAccessible(node));
@ -1006,12 +1009,13 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
}
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
!content->IsFocusable()) { // For presentation only
// Only create accessible for role of "presentation" if it is focusable --
// in that case we need an accessible in case it gets focused, we
// don't want focus ever to be 'lost'
return nsnull;
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation")) {
// Ignore presentation role if element is focusable (focus event shouldn't
// be ever lost and should be sensible).
if (content->IsFocusable())
roleMapEntry = nsnull;
else
return nsnull;
}
if (weakFrame.IsAlive() && !newAcc && isHTML) { // HTML accessibles

View File

@ -484,18 +484,22 @@ STDMETHODIMP nsAccessibleWrap::get_accKeyboardShortcut(
/* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
{
__try {
if (!pszKeyboardShortcut)
return E_INVALIDARG;
*pszKeyboardShortcut = NULL;
nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
if (xpAccessible) {
nsAutoString shortcut;
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
if (NS_FAILED(rv))
return E_FAIL;
if (!xpAccessible || xpAccessible->IsDefunct())
return E_FAIL;
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
shortcut.Length());
return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
}
nsAutoString shortcut;
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
if (NS_FAILED(rv))
return GetHRESULT(rv);
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
shortcut.Length());
return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}

View File

@ -673,14 +673,19 @@ nsXULTreeGridRowAccessible::GetName(nsAString& aName)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeColumns> columns;
mTree->GetColumns(getter_AddRefs(columns));
if (columns) {
nsCOMPtr<nsITreeColumn> primaryColumn;
columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
if (primaryColumn)
GetCellName(primaryColumn, aName);
// XXX: the row name sholdn't be a concatenation of cell names (bug 664384).
nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
while (column) {
if (!aName.IsEmpty())
aName.AppendLiteral(" ");
nsAutoString cellName;
GetCellName(column, cellName);
aName.Append(cellName);
column = nsCoreUtils::GetNextSensibleColumn(column);
}
return NS_OK;
}

View File

@ -103,7 +103,7 @@
<button id="btn_namefromcontent" title="title">1</button>
<!-- button, no name from content, ARIA role overrides this rule -->
<button id="btn_nonamefromcontent" role="presentation">1</button>
<button id="btn_nonamefromcontent" role="img">1</button>
<!-- button, no content, name from @title -->
<button id="btn_title" title="title"></button>

View File

@ -88,8 +88,7 @@
title="title"><img alt="img title" /></a>
<!-- no name from content, ARIA role overrides this rule -->
<a id="nonamefromcontent" href="mozilla.org"
role="presentation">1</a>
<a id="nonamefromcontent" href="mozilla.org" role="img">1</a>
<br/>
<!-- no content, name from @title -->

View File

@ -86,7 +86,7 @@
}
}
function tableTester(aID)
function tableTester(aID, aIsTable, aCol1ID, aCol2ID)
{
this.DOMNode = getNode(aID);
@ -98,7 +98,7 @@
this.check = function tableTester_check(aEvent)
{
var tree = {
role: ROLE_TREE_TABLE,
role: aIsTable ? ROLE_TABLE : ROLE_TREE_TABLE,
children: [
{
role: ROLE_LIST
@ -109,15 +109,15 @@
{
role: ROLE_GRID_CELL,
children: [],
name: "row0_col1"
name: "row0_" + aCol1ID
},
{
role: ROLE_GRID_CELL,
children: [],
name: "row0_col2"
name: "row0_" + aCol2ID
}
],
name: "row0_col1"
name: "row0_" + aCol1ID + " row0_" + aCol2ID
},
{
role: ROLE_ROW,
@ -125,15 +125,15 @@
{
role: ROLE_GRID_CELL,
children: [],
name: "row1_col1"
name: "row1_" + aCol1ID
},
{
role: ROLE_GRID_CELL,
children: [],
name: "row1_col2"
name: "row1_" + aCol2ID
}
],
name: "row1_col1"
name: "row1_" + aCol1ID + " row1_" + aCol2ID
}
]
};
@ -152,7 +152,8 @@
var gQueue = new eventQueue(EVENT_REORDER);
gQueue.push(new treeTester("tree"));
gQueue.push(new tableTester("table"));
gQueue.push(new tableTester("table", true, "t_col1", "t_col2"));
gQueue.push(new tableTester("treetable", false, "tt_col1", "tt_col2"));
gQueue.invoke(); // Will call SimpleTest.finish()
}
@ -170,7 +171,12 @@
title="Treegrid row accessible shouldn't inherit name from tree accessible">
Mozilla Bug 546812
</a>
<p id="display"></p>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=664376"
title="Table rows of XUL trees no longer containing cell content as accessible name">
Mozilla Bug 664376
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
@ -188,8 +194,16 @@
<tree id="table" flex="1">
<treecols>
<treecol id="col1" flex="1" label="column" primary="true"/>
<treecol id="col2" flex="1" label="column 2"/>
<treecol id="t_col1" flex="1" label="column"/>
<treecol id="t_col2" flex="1" label="column 2"/>
</treecols>
<treechildren/>
</tree>
<tree id="treetable" flex="1">
<treecols>
<treecol id="tt_col1" flex="1" label="column" primary="true"/>
<treecol id="tt_col2" flex="1" label="column 2"/>
</treecols>
<treechildren/>
</tree>

View File

@ -57,6 +57,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
is(accessibleTable.getCellAt(0,0).firstChild.name, "hi", "no cell");
}
//////////////////////////////////////////////////////////////////////////
// test gEmptyRoleMap
testRole("cell", ROLE_NOTHING);
@ -67,10 +68,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
for (a in abstract_roles)
testRole(abstract_roles[a], ROLE_SECTION);
//////////////////////////////////////////////////////////////////////////
// misc roles
testRole("scrollbar", ROLE_SCROLLBAR);
testRole("dir", ROLE_LIST);
//////////////////////////////////////////////////////////////////////////
// test document role map update
var testDoc = getAccessible(document, [nsIAccessibleDocument]);
testRole(testDoc, ROLE_DOCUMENT);

View File

@ -50,6 +50,7 @@ _TEST_FILES =\
$(warning test_applicationacc.xul temporarily disabled, see bug 561508) \
test_aria_globals.html \
test_aria_imgmap.html \
test_aria_presentation.html \
test_button.xul \
test_combobox.xul \
test_cssoverflow.html \

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<title>Test accessible tree when ARIA role presentation is used</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript">
function doTest()
{
// Presentation role don't allow accessible.
var tree =
{ SECTION: [ // container
{ TEXT_LEAF: [ ] } // child text of presentation node
] };
testAccessibleTree("div_cnt", tree);
// Focusable element, presentation role is ignored.
tree =
{ SECTION: [ // container
{ PUSHBUTTON: [ // button
{ TEXT_LEAF: [ ] }
] }
] };
testAccessibleTree("btn_cnt", tree);
// Presentation table, no table structure is exposed.
tree =
{ SECTION: [ // container
{ TEXT_LEAF: [ ] } // cell text
] };
testAccessibleTree("tbl_cnt", tree);
// Focusable table, presentation role is ignored.
tree =
{ SECTION: [ // container
{ TABLE: [ // table
{ ROW: [ // tr
{ CELL: [ //td
{ TEXT_LEAF: [ ] }
] }
] }
] }
] };
testAccessibleTree("tblfocusable_cnt", tree);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=548291"
title="Accessible tree of ARIA image maps">
Mozilla Bug 548291
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=666504"
title="Ignore role presentation on focusable elements">
Mozilla Bug 666504
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="div_cnt"><div role="presentation">text</div></div>
<div id="btn_cnt"><button role="presentation">btn</button></div>
<div id="tbl_cnt">
<table role="presentation">
<tr>
<td>cell</td>
</tr>
</table>
</div>
<div id="tblfocusable_cnt">
<table role="presentation" tabindex="0">
<tr>
<td>cell</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -18,7 +18,11 @@ function nsTreeTreeView()
];
}
function nsTreeView() { }
function nsTreeView()
{
this.mTree = null;
this.mData = [];
}
nsTreeView.prototype =
{
@ -205,8 +209,6 @@ nsTreeView.prototype =
return rowIdx;
},
mTree: null,
mData: [],
mCyclerStates: [
createAtom("cyclerState1"),
createAtom("cyclerState2"),

View File

@ -15,6 +15,7 @@ function test() {
if (topic != "page-info-dialog-loaded")
return;
Services.obs.removeObserver(observer, topic);
handlePageInfo();
}

View File

@ -1616,6 +1616,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
margin: 0;
padding: 2px 0 4px;
-moz-border-image: url(tabbrowser/tab.png) 4 3 0 / 4px 3px 0 repeat stretch;
border-radius: 0;
}
.tabbrowser-tab:hover,

View File

@ -6929,7 +6929,7 @@ dnl ========================================================
dnl Defaults
case "${target}" in
arm-android-eabi)
arm-android*|arm-linuxandroid*)
MOZ_THUMB=yes
MOZ_ARCH=armv7-a
MOZ_FPU=vfp

View File

@ -946,6 +946,10 @@ public:
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
PRInt64 SizeOf() const {
return sizeof(*this);
}
protected:
/**
* Hook for implementing GetID. This is guaranteed to only be

View File

@ -1534,6 +1534,8 @@ public:
#undef DEPRECATED_OPERATION
void WarnOnceAbout(DeprecatedOperations aOperation);
PRInt64 SizeOf() const;
private:
PRUint32 mWarnedAbout;

View File

@ -8375,3 +8375,16 @@ nsDocument::CreateTouchList(nsIVariant* aPoints,
return NS_OK;
}
PRInt64
nsIDocument::SizeOf() const
{
PRInt64 size = sizeof(*this);
for (nsIContent* node = GetFirstChild(); node;
node = node->GetNextNode(this)) {
size += node->SizeOf();
}
return size;
}

View File

@ -3669,15 +3669,15 @@ nsGenericElement::SaveSubtreeState()
// Generic DOMNode implementations
// When replacing, aRefContent is the content being replaced; when
// When replacing, aRefChild is the content being replaced; when
// inserting it's the content before which we're inserting. In the
// latter case it may be null.
static
PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
PRBool aIsReplace, nsIContent* aRefContent)
PRBool aIsReplace, nsINode* aRefChild)
{
NS_PRECONDITION(aNewChild, "Must have new child");
NS_PRECONDITION(!aIsReplace || aRefContent,
NS_PRECONDITION(!aIsReplace || aRefChild,
"Must have ref content for replace");
NS_PRECONDITION(aParent->IsNodeOfType(nsINode::eDOCUMENT) ||
aParent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) ||
@ -3712,12 +3712,12 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
if (rootElement) {
// Already have a documentElement, so this is only OK if we're
// replacing it.
return aIsReplace && rootElement == aRefContent;
return aIsReplace && rootElement == aRefChild;
}
// We don't have a documentElement yet. Our one remaining constraint is
// that the documentElement must come after the doctype.
if (!aRefContent) {
if (!aRefChild) {
// Appending is just fine.
return PR_TRUE;
}
@ -3735,7 +3735,7 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
}
PRInt32 doctypeIndex = aParent->IndexOf(docTypeContent);
PRInt32 insertIndex = aParent->IndexOf(aRefContent);
PRInt32 insertIndex = aParent->IndexOf(aRefChild);
// Now we're OK in the following two cases only:
// 1) We're replacing something that's not before the doctype
@ -3757,7 +3757,7 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
if (docTypeContent) {
// Already have a doctype, so this is only OK if we're replacing it
return aIsReplace && docTypeContent == aRefContent;
return aIsReplace && docTypeContent == aRefChild;
}
// We don't have a doctype yet. Our one remaining constraint is
@ -3769,17 +3769,17 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
return PR_TRUE;
}
if (!aRefContent) {
if (!aRefChild) {
// Trying to append a doctype, but have a documentElement
return PR_FALSE;
}
PRInt32 rootIndex = aParent->IndexOf(rootElement);
PRInt32 insertIndex = aParent->IndexOf(aRefContent);
PRInt32 insertIndex = aParent->IndexOf(aRefChild);
// Now we're OK if and only if insertIndex <= rootIndex. Indeed, either
// we end up replacing aRefContent or we end up before it. Either one is
// ok as long as aRefContent is not after rootElement.
// we end up replacing aRefChild or we end up before it. Either one is
// ok as long as aRefChild is not after rootElement.
return insertIndex <= rootIndex;
}
case nsIDOMNode::DOCUMENT_FRAGMENT_NODE :
@ -3806,8 +3806,7 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
}
// If we can put this content at the the right place, we might be ok;
// if not, we bail out.
if (!IsAllowedAsChild(childContent, aParent, aIsReplace,
aRefContent)) {
if (!IsAllowedAsChild(childContent, aParent, aIsReplace, aRefChild)) {
return PR_FALSE;
}
}
@ -3877,8 +3876,9 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
// If we're replacing, fire for node-to-be-replaced
if (aReplace) {
// If we're replacing, fire for node-to-be-replaced.
// If aRefChild == aNewChild then we'll fire for it in check below
if (aReplace && aRefChild != aNewChild) {
nsContentUtils::MaybeFireNodeRemoved(aRefChild, this, GetOwnerDoc());
}
@ -3899,7 +3899,6 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
nsIDocument* doc = GetOwnerDoc();
nsIContent* newContent = static_cast<nsIContent*>(aNewChild);
nsIContent* refContent;
PRInt32 insPos;
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, PR_TRUE);
@ -3910,23 +3909,13 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
if (insPos < 0) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
if (aRefChild == aNewChild) {
return NS_OK;
}
NS_ASSERTION(aRefChild->IsNodeOfType(eCONTENT),
"A child node must be nsIContent!");
refContent = static_cast<nsIContent*>(aRefChild);
}
else {
insPos = GetChildCount();
refContent = nsnull;
}
// Make sure that the inserted node is allowed as a child of its new parent.
if (!IsAllowedAsChild(newContent, this, aReplace, refContent)) {
if (!IsAllowedAsChild(newContent, this, aReplace, aRefChild)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
@ -3934,8 +3923,6 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
// If we're replacing
if (aReplace) {
refContent = GetChildAt(insPos + 1);
res = RemoveChildAt(insPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
}
@ -3956,9 +3943,6 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
NS_ERROR("How come our flags didn't catch this?");
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
NS_ASSERTION(!(oldParent == this && removeIndex == insPos),
"invalid removeIndex");
res = oldParent->RemoveChildAt(removeIndex, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);

View File

@ -36,7 +36,7 @@ function testFile(file, contents, test) {
[{ name: "hello", value: "world"},
{ name: "myfile",
value: contents,
fileName: file.name || "",
fileName: file.name || "blob",
contentType: file.type || "application/octet-stream" }]);
testHasRun();
}

View File

@ -57,13 +57,15 @@
#include "nsTArray.h"
#include "CanvasUtils.h"
#include "mozilla/gfx/Matrix.h"
using namespace mozilla;
namespace mozilla {
namespace CanvasUtils {
void
CanvasUtils::DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly)
DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly)
{
// Callers should ensure that mCanvasElement is non-null before calling this
if (!aCanvasElement) {
@ -96,7 +98,7 @@ CanvasUtils::DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
}
void
CanvasUtils::LogMessage (const nsCString& errorString)
LogMessage (const nsCString& errorString)
{
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (!console)
@ -107,7 +109,7 @@ CanvasUtils::LogMessage (const nsCString& errorString)
}
void
CanvasUtils::LogMessagef (const char *fmt, ...)
LogMessagef (const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@ -122,3 +124,116 @@ CanvasUtils::LogMessagef (const char *fmt, ...)
va_end(ap);
}
bool
CoerceDouble(jsval v, double* d)
{
if (JSVAL_IS_DOUBLE(v)) {
*d = JSVAL_TO_DOUBLE(v);
} else if (JSVAL_IS_INT(v)) {
*d = double(JSVAL_TO_INT(v));
} else if (JSVAL_IS_VOID(v)) {
*d = 0.0;
} else {
return false;
}
return true;
}
template<size_t N>
static bool
JSValToMatrixElts(JSContext* cx, const jsval& val,
double* (&elts)[N], nsresult* rv)
{
JSObject* obj;
jsuint length;
if (JSVAL_IS_PRIMITIVE(val) ||
!(obj = JSVAL_TO_OBJECT(val)) ||
!JS_GetArrayLength(cx, obj, &length) ||
N != length) {
// Not an array-like thing or wrong size
*rv = NS_ERROR_INVALID_ARG;
return false;
}
for (PRUint32 i = 0; i < N; ++i) {
jsval elt;
double d;
if (!JS_GetElement(cx, obj, i, &elt)) {
*rv = NS_ERROR_FAILURE;
return false;
}
if (!CoerceDouble(elt, &d)) {
*rv = NS_ERROR_INVALID_ARG;
return false;
}
if (!FloatValidate(d)) {
// This is weird, but it's the behavior of SetTransform()
*rv = NS_OK;
return false;
}
*elts[i] = d;
}
*rv = NS_OK;
return true;
}
bool
JSValToMatrix(JSContext* cx, const jsval& val, gfxMatrix* matrix, nsresult* rv)
{
double* elts[] = { &matrix->xx, &matrix->yx, &matrix->xy, &matrix->yy,
&matrix->x0, &matrix->y0 };
return JSValToMatrixElts(cx, val, elts, rv);
}
bool
JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv)
{
gfxMatrix m;
if (!JSValToMatrix(cx, val, &m, rv))
return false;
*matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy),
Float(m.x0), Float(m.y0));
return true;
}
template<size_t N>
static nsresult
MatrixEltsToJSVal(/*const*/ jsval (&elts)[N], JSContext* cx, jsval* val)
{
JSObject* obj = JS_NewArrayObject(cx, N, elts);
if (!obj) {
return NS_ERROR_OUT_OF_MEMORY;
}
*val = OBJECT_TO_JSVAL(obj);
return NS_OK;
}
nsresult
MatrixToJSVal(const gfxMatrix& matrix, JSContext* cx, jsval* val)
{
jsval elts[] = {
DOUBLE_TO_JSVAL(matrix.xx), DOUBLE_TO_JSVAL(matrix.yx),
DOUBLE_TO_JSVAL(matrix.xy), DOUBLE_TO_JSVAL(matrix.yy),
DOUBLE_TO_JSVAL(matrix.x0), DOUBLE_TO_JSVAL(matrix.y0)
};
return MatrixEltsToJSVal(elts, cx, val);
}
nsresult
MatrixToJSVal(const Matrix& matrix, JSContext* cx, jsval* val)
{
jsval elts[] = {
DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
};
return MatrixEltsToJSVal(elts, cx, val);
}
} // namespace CanvasUtils
} // namespace mozilla

View File

@ -47,37 +47,178 @@ class nsIPrincipal;
namespace mozilla {
class CanvasUtils {
public:
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
namespace gfx {
class Matrix;
}
static PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
PRInt32 realWidth, PRInt32 realHeight) {
CheckedInt32 checked_x_plus_w = CheckedInt32(x) + w;
CheckedInt32 checked_y_plus_h = CheckedInt32(y) + h;
namespace CanvasUtils {
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
checked_x_plus_w.valid() &&
checked_x_plus_w.value() <= realWidth &&
checked_y_plus_h.valid() &&
checked_y_plus_h.value() <= realHeight;
using namespace gfx;
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
inline PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
PRInt32 realWidth, PRInt32 realHeight) {
CheckedInt32 checked_xmost = CheckedInt32(x) + w;
CheckedInt32 checked_ymost = CheckedInt32(y) + h;
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
checked_xmost.valid() &&
checked_xmost.value() <= realWidth &&
checked_ymost.valid() &&
checked_ymost.value() <= realHeight;
}
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
// onto it would make it such.
void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly);
void LogMessage (const nsCString& errorString);
void LogMessagef (const char *fmt, ...);
// Make a double out of |v|, treating undefined values as 0.0 (for
// the sake of sparse arrays). Return true iff coercion
// succeeded.
bool CoerceDouble(jsval v, double* d);
// Return true iff the conversion succeeded, false otherwise. *rv is
// the value to return to script if this returns false.
bool JSValToMatrix(JSContext* cx, const jsval& val,
gfxMatrix* matrix, nsresult* rv);
bool JSValToMatrix(JSContext* cx, const jsval& val,
Matrix* matrix, nsresult* rv);
nsresult MatrixToJSVal(const gfxMatrix& matrix,
JSContext* cx, jsval* val);
nsresult MatrixToJSVal(const Matrix& matrix,
JSContext* cx, jsval* val);
/* Float validation stuff */
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
inline PRBool FloatValidate (double f1) {
VALIDATE(f1);
return PR_TRUE;
}
inline PRBool FloatValidate (double f1, double f2) {
VALIDATE(f1); VALIDATE(f2);
return PR_TRUE;
}
inline PRBool FloatValidate (double f1, double f2, double f3) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
return PR_TRUE;
}
inline PRBool FloatValidate (double f1, double f2, double f3, double f4) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
return PR_TRUE;
}
inline PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
return PR_TRUE;
}
inline PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
return PR_TRUE;
}
#undef VALIDATE
template<typename T>
nsresult
JSValToDashArray(JSContext* cx, const jsval& val,
FallibleTArray<T>& dashArray);
template<typename T>
nsresult
DashArrayToJSVal(FallibleTArray<T>& dashArray,
JSContext* cx, jsval* val);
template<typename T>
nsresult
JSValToDashArray(JSContext* cx, const jsval& patternArray,
FallibleTArray<T>& dashes)
{
// The cap is pretty arbitrary. 16k should be enough for
// anybody...
static const jsuint MAX_NUM_DASHES = 1 << 14;
if (!JSVAL_IS_PRIMITIVE(patternArray)) {
JSObject* obj = JSVAL_TO_OBJECT(patternArray);
jsuint length;
if (!JS_GetArrayLength(cx, obj, &length)) {
// Not an array-like thing
return NS_ERROR_INVALID_ARG;
} else if (length > MAX_NUM_DASHES) {
// Too many dashes in the pattern
return NS_ERROR_ILLEGAL_VALUE;
}
bool haveNonzeroElement = false;
for (jsint i = 0; i < jsint(length); ++i) {
jsval elt;
double d;
if (!JS_GetElement(cx, obj, i, &elt)) {
return NS_ERROR_FAILURE;
}
if (!(CoerceDouble(elt, &d) &&
FloatValidate(d) &&
d >= 0.0)) {
// Pattern elements must be finite "numbers" >= 0.
return NS_ERROR_INVALID_ARG;
} else if (d > 0.0) {
haveNonzeroElement = true;
}
if (!dashes.AppendElement(d)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
if (dashes.Length() > 0 && !haveNonzeroElement) {
// An all-zero pattern makes no sense.
return NS_ERROR_ILLEGAL_VALUE;
}
} else if (!(JSVAL_IS_VOID(patternArray) || JSVAL_IS_NULL(patternArray))) {
// undefined and null mean "reset to no dash". Any other
// random garbage is a type error.
return NS_ERROR_INVALID_ARG;
}
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
// onto it would make it such.
return NS_OK;
}
static void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly);
static void LogMessage (const nsCString& errorString);
static void LogMessagef (const char *fmt, ...);
private:
// this can't be instantiated
CanvasUtils() { }
};
template<typename T>
nsresult
DashArrayToJSVal(FallibleTArray<T>& dashes,
JSContext* cx, jsval* val)
{
if (dashes.IsEmpty()) {
*val = JSVAL_NULL;
} else {
JSObject* obj = JS_NewArrayObject(cx, dashes.Length(), nsnull);
if (!obj) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0; i < dashes.Length(); ++i) {
double d = dashes[i];
jsval elt = DOUBLE_TO_JSVAL(d);
if (!JS_SetElement(cx, obj, i, &elt)) {
return NS_ERROR_FAILURE;
}
}
*val = OBJECT_TO_JSVAL(obj);
}
return NS_OK;
}
}
}
#endif /* _CANVASUTILS_H_ */

View File

@ -119,51 +119,16 @@
// windows.h (included by chromium code) defines this, in its infinite wisdom
#undef DrawText
using namespace mozilla::ipc;
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::CanvasUtils;
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layers;
static float kDefaultFontSize = 10.0;
static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
/* Float validation stuff */
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
static PRBool FloatValidate (double f1) {
VALIDATE(f1);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2) {
VALIDATE(f1); VALIDATE(f2);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
return PR_TRUE;
}
#undef VALIDATE
/* Memory reporter stuff */
static nsIMemoryReporter *gCanvasMemoryReporter = nsnull;
static PRInt64 gCanvasMemoryUsed = 0;
@ -202,6 +167,12 @@ CopyContext(gfxContext* dest, gfxContext* src)
dest->SetFillRule(src->CurrentFillRule());
dest->SetAntialiasMode(src->CurrentAntialiasMode());
AutoFallibleTArray<gfxFloat, 10> dashes;
double dashOffset;
if (src->CurrentDash(dashes, &dashOffset)) {
dest->SetDash(dashes.Elements(), dashes.Length(), dashOffset);
}
}
/**
@ -1436,6 +1407,64 @@ nsCanvasRenderingContext2D::SetTransform(float m11, float m12, float m21, float
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetMozCurrentTransform(JSContext* cx,
const jsval& matrix)
{
nsresult rv;
gfxMatrix newCTM;
if (!JSValToMatrix(cx, matrix, &newCTM, &rv)) {
return rv;
}
mThebes->SetMatrix(newCTM);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
jsval* matrix)
{
return MatrixToJSVal(mThebes->CurrentMatrix(), cx, matrix);
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
const jsval& matrix)
{
nsresult rv;
gfxMatrix newCTMInverse;
if (!JSValToMatrix(cx, matrix, &newCTMInverse, &rv)) {
return rv;
}
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
if (!newCTMInverse.IsSingular()) {
mThebes->SetMatrix(newCTMInverse.Invert());
}
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
jsval* matrix)
{
gfxMatrix ctm = mThebes->CurrentMatrix();
if (!mThebes->CurrentMatrix().IsSingular()) {
ctm.Invert();
} else {
double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
ctm = gfxMatrix(NaN, NaN, NaN, NaN, NaN, NaN);
}
return MatrixToJSVal(ctm, cx, matrix);
}
//
// colors
//
@ -2593,7 +2622,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProces
mBoundingBox = mBoundingBox.Union(textRunMetrics.mBoundingBox);
}
return static_cast<nscoord>(textRunMetrics.mAdvanceWidth/gfxFloat(mAppUnitsPerDevPixel));
return NSToCoordRound(textRunMetrics.mAdvanceWidth);
}
virtual void DrawText(nscoord xOffset, nscoord width)
@ -2744,7 +2773,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
processor.mFontgrp = GetCurrentFontStyle();
NS_ASSERTION(processor.mFontgrp, "font group is null");
nscoord totalWidth;
nscoord totalWidthCoord;
// calls bidi algo twice since it needs the full text width and the
// bounding boxes before rendering anything
@ -2756,12 +2785,13 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
nsBidiPresUtils::MODE_MEASURE,
nsnull,
0,
&totalWidth);
&totalWidthCoord);
if (NS_FAILED(rv))
return rv;
float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel;
if (aWidth)
*aWidth = static_cast<float>(totalWidth);
*aWidth = totalWidth;
// if only measuring, don't need to do any more work
if (aOp==TEXT_DRAW_OPERATION_MEASURE)
@ -3263,6 +3293,59 @@ nsCanvasRenderingContext2D::GetMiterLimit(float *miter)
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray)
{
AutoFallibleTArray<gfxFloat, 10> dashes;
nsresult rv = JSValToDashArray(cx, patternArray, dashes);
if (NS_SUCCEEDED(rv)) {
mThebes->SetDash(dashes.Elements(), dashes.Length(),
mThebes->CurrentDashOffset());
}
return rv;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray)
{
AutoFallibleTArray<gfxFloat, 10> dashes;
if (!mThebes->CurrentDash(dashes, nsnull)) {
dashes.SetLength(0);
}
return DashArrayToJSVal(dashes, cx, dashArray);
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetMozDashOffset(float offset)
{
if (!FloatValidate(offset)) {
return NS_ERROR_ILLEGAL_VALUE;
}
AutoFallibleTArray<gfxFloat, 10> dashes;
if (!mThebes->CurrentDash(dashes, nsnull)) {
// Either no dash is set or the cairo call failed. Either
// way, eat the error.
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_OK;
}
NS_ABORT_IF_FALSE(dashes.Length() > 0,
"CurrentDash() should have returned false");
mThebes->SetDash(dashes.Elements(), dashes.Length(),
gfxFloat(offset));
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetMozDashOffset(float* offset)
{
*offset = float(mThebes->CurrentDashOffset());
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::IsPointInPath(float x, float y, PRBool *retVal)
{

View File

@ -127,11 +127,12 @@
#undef DrawText
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::CanvasUtils;
using namespace mozilla::css;
using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::ipc;
using namespace mozilla::css;
using namespace mozilla::layers;
namespace mgfx = mozilla::gfx;
@ -139,41 +140,6 @@ static float kDefaultFontSize = 10.0;
static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
/* Float validation stuff */
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
static PRBool FloatValidate (double f1) {
VALIDATE(f1);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2) {
VALIDATE(f1); VALIDATE(f2);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
return PR_TRUE;
}
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
return PR_TRUE;
}
#undef VALIDATE
/* Memory reporter stuff */
static nsIMemoryReporter *gCanvasAzureMemoryReporter = nsnull;
static PRInt64 gCanvasAzureMemoryUsed = 0;
@ -605,6 +571,10 @@ protected:
*/
PRPackedBool mPredictManyRedrawCalls;
// This is stored after GetThebesSurface has been called once to avoid
// excessive ThebesSurface initialization overhead.
nsRefPtr<gfxASurface> mThebesSurface;
/**
* We also have a device space pathbuilder. The reason for this is as
* follows, when a path is being built, but the transform changes, we
@ -718,6 +688,7 @@ protected:
miterLimit(10.0f),
globalAlpha(1.0f),
shadowBlur(0.0),
dashOffset(0.0f),
op(OP_OVER),
fillRule(FILL_WINDING),
lineCap(CAP_BUTT),
@ -737,6 +708,8 @@ protected:
miterLimit(other.miterLimit),
globalAlpha(other.globalAlpha),
shadowBlur(other.shadowBlur),
dash(other.dash),
dashOffset(other.dashOffset),
op(other.op),
fillRule(FILL_WINDING),
lineCap(other.lineCap),
@ -795,6 +768,8 @@ protected:
Float miterLimit;
Float globalAlpha;
Float shadowBlur;
FallibleTArray<Float> dash;
Float dashOffset;
CompositionOp op;
FillRule fillRule;
@ -1090,9 +1065,14 @@ nsCanvasRenderingContext2DAzure::Reset()
}
mTarget = nsnull;
// Since the target changes the backing texture will change, and this will
// no longer be valid.
mThebesSurface = nsnull;
mValid = PR_FALSE;
mIsEntireFrameInvalid = PR_FALSE;
mPredictManyRedrawCalls = PR_FALSE;
return NS_OK;
}
@ -1625,6 +1605,62 @@ nsCanvasRenderingContext2DAzure::SetTransform(float m11, float m12, float m21, f
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetMozCurrentTransform(JSContext* cx,
const jsval& matrix)
{
nsresult rv;
Matrix newCTM;
if (!JSValToMatrix(cx, matrix, &newCTM, &rv)) {
return rv;
}
mTarget->SetTransform(newCTM);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
jsval* matrix)
{
return MatrixToJSVal(mTarget->GetTransform(), cx, matrix);
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetMozCurrentTransformInverse(JSContext* cx,
const jsval& matrix)
{
nsresult rv;
Matrix newCTMInverse;
if (!JSValToMatrix(cx, matrix, &newCTMInverse, &rv)) {
return rv;
}
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
if (newCTMInverse.Invert()) {
mTarget->SetTransform(newCTMInverse);
}
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::GetMozCurrentTransformInverse(JSContext* cx,
jsval* matrix)
{
Matrix ctm = mTarget->GetTransform();
if (!ctm.Invert()) {
double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
ctm = Matrix(NaN, NaN, NaN, NaN, NaN, NaN);
}
return MatrixToJSVal(ctm, cx, matrix);
}
//
// colors
//
@ -2050,8 +2086,6 @@ nsCanvasRenderingContext2DAzure::FillRect(float x, float y, float w, float h)
return NS_OK;
}
bool doDrawShadow = NeedToDrawShadow();
const ContextState &state = CurrentState();
if (state.patternStyles[STYLE_FILL]) {
@ -2127,7 +2161,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
StrokeLine(Point(x, y), Point(x + w, y),
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
cap, state.miterLimit),
cap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, state.op));
return NS_OK;
} else if (!w) {
@ -2139,7 +2176,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
StrokeLine(Point(x, y), Point(x, y + h),
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
cap, state.miterLimit),
cap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, state.op));
return NS_OK;
}
@ -2148,7 +2188,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
StrokeRect(mgfx::Rect(x, y, w, h),
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit),
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, state.op));
return Redraw();
@ -2212,7 +2255,10 @@ nsCanvasRenderingContext2DAzure::Stroke()
AdjustedTarget(this)->
Stroke(mPath, GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit),
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, state.op));
return Redraw();
@ -2434,8 +2480,6 @@ nsCanvasRenderingContext2DAzure::Arc(float x, float y,
// Calculate the total arc we're going to sweep.
Float arcSweepLeft = abs(endAngle - startAngle);
// Calculate the amount of curves needed, 1 per quarter circle.
Float curves = ceil(arcSweepLeft / (M_PI / 2.0f));
Float sweepDirection = ccw ? -1.0f : 1.0f;
@ -2953,6 +2997,8 @@ nsCanvasRenderingContext2DAzure::MeasureText(const nsAString& rawText,
*/
struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiProcessor
{
typedef nsCanvasRenderingContext2DAzure::ContextState ContextState;
virtual void SetText(const PRUnichar* text, PRInt32 length, nsBidiDirection direction)
{
mTextRun = gfxTextRunCache::MakeTextRun(text,
@ -3017,7 +3063,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
Point baselineOrigin =
Point(point.x * devUnitsPerAppUnit, point.y * devUnitsPerAppUnit);
for (int c = 0; c < numRuns; c++) {
for (PRUint32 c = 0; c < numRuns; c++) {
gfxFont *font = runs[c].mFont;
PRUint32 endRun = 0;
if (c + 1 < numRuns) {
@ -3037,7 +3083,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
float advanceSum = 0;
for (int i = runs[c].mCharacterOffset; i < endRun; i++) {
for (PRUint32 i = runs[c].mCharacterOffset; i < endRun; i++) {
Glyph newGlyph;
if (glyphs[i].IsSimpleGlyph()) {
newGlyph.mIndex = glyphs[i].GetSimpleGlyph();
@ -3060,7 +3106,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
gfxTextRun::DetailedGlyph *detailedGlyphs =
mTextRun->GetDetailedGlyphs(i);
for (int c = 0; c < glyphs[i].GetGlyphCount(); c++) {
for (PRUint32 c = 0; c < glyphs[i].GetGlyphCount(); c++) {
newGlyph.mIndex = detailedGlyphs[c].mGlyphID;
if (mTextRun->IsRightToLeft()) {
newGlyph.mPosition.x = baselineOrigin.x + detailedGlyphs[c].mXOffset * devUnitsPerAppUnit -
@ -3093,12 +3139,16 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
Matrix oldTransform = mCtx->mTarget->GetTransform();
const ContextState& state = *mState;
nsCanvasRenderingContext2DAzure::AdjustedTarget(mCtx)->
Stroke(path, nsCanvasRenderingContext2DAzure::GeneralPattern().
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
StrokeOptions(mCtx->CurrentState().lineWidth, mCtx->CurrentState().lineJoin,
mCtx->CurrentState().lineCap, mCtx->CurrentState().miterLimit),
DrawOptions(mState->globalAlpha, mState->op));
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, state.op));
}
}
@ -3126,7 +3176,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
nsCanvasRenderingContext2DAzure::TextDrawOperation mOp;
// context state
nsCanvasRenderingContext2DAzure::ContextState *mState;
ContextState *mState;
// union of bounding boxes of all runs, needed for shadows
gfxRect mBoundingBox;
@ -3524,6 +3574,47 @@ nsCanvasRenderingContext2DAzure::GetMiterLimit(float *miter)
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetMozDash(JSContext *cx, const jsval& patternArray)
{
FallibleTArray<Float> dash;
nsresult rv = JSValToDashArray(cx, patternArray, dash);
if (NS_SUCCEEDED(rv)) {
ContextState& state = CurrentState();
state.dash = dash;
if (state.dash.IsEmpty()) {
state.dashOffset = 0;
}
}
return rv;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::GetMozDash(JSContext* cx, jsval* dashArray)
{
return DashArrayToJSVal(CurrentState().dash, cx, dashArray);
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetMozDashOffset(float offset)
{
if (!FloatValidate(offset)) {
return NS_ERROR_ILLEGAL_VALUE;
}
ContextState& state = CurrentState();
if (!state.dash.IsEmpty()) {
state.dashOffset = offset;
}
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::GetMozDashOffset(float* offset)
{
*offset = CurrentState().dashOffset;
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::IsPointInPath(float x, float y, PRBool *retVal)
{
@ -4030,8 +4121,6 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU
memset(aData, 0, aDataLen);
}
bool finishedPainting = false;
IntRect srcReadRect = srcRect.Intersect(destRect);
IntRect dstWriteRect = srcReadRect;
dstWriteRect.MoveBy(-x, -y);
@ -4055,8 +4144,8 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU
// from src and advancing that ptr before writing to dst.
PRUint8 *dst = aData + dstWriteRect.y * (w * 4) + dstWriteRect.x * 4;
for (PRUint32 j = 0; j < dstWriteRect.height; j++) {
for (PRUint32 i = 0; i < dstWriteRect.width; i++) {
for (int j = 0; j < dstWriteRect.height; j++) {
for (int i = 0; i < dstWriteRect.width; i++) {
// XXX Is there some useful swizzle MMX we can use here?
#ifdef IS_LITTLE_ENDIAN
PRUint8 b = *src++;
@ -4238,11 +4327,22 @@ nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface)
*surface = tmpSurf.forget().get();
return NS_OK;
}
nsRefPtr<gfxASurface> newSurf =
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
*surface = newSurf.forget().get();
if (!mThebesSurface) {
mThebesSurface =
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
if (!mThebesSurface) {
return NS_ERROR_FAILURE;
}
} else {
// Normally GetThebesSurfaceForDrawTarget will handle the flush, when
// we're returning a cached ThebesSurface we need to flush here.
mTarget->Flush();
}
mThebesSurface->AddRef();
*surface = mThebesSurface;
return NS_OK;
}

View File

@ -36,15 +36,16 @@ function check() {
});
}
var nodes;
var testName;
var nodes = getNodes();
var testName = "empty";
var mutateCount = 0;
nodes = getNodes();
check("empty");
check();
// Set up listeners
root = $('content');
root.addEventListener("DOMNodeInserted", function(e) {
mutateCount++;
is(e.isTrusted, true, "untrusted mutation event");
var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null, false);
do {
@ -53,6 +54,7 @@ root.addEventListener("DOMNodeInserted", function(e) {
} while(w.nextNode());
}, false);
root.addEventListener("DOMNodeRemoved", function(e) {
mutateCount++;
is(e.isTrusted, true, "untrusted mutation event");
var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null, false);
do {
@ -110,6 +112,48 @@ testName = "normalizing";
root.normalize();
check();
testName = "self replace firstChild";
mutateCount = 0;
root.replaceChild(root.firstChild, root.firstChild);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "self replace second child";
mutateCount = 0;
root.replaceChild(root.firstChild.nextSibling, root.firstChild.nextSibling);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "self replace lastChild";
mutateCount = 0;
root.replaceChild(root.lastChild, root.lastChild);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "self insertBefore firstChild";
mutateCount = 0;
root.insertBefore(root.firstChild, root.firstChild);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "self insertBefore second child";
mutateCount = 0;
root.insertBefore(root.firstChild.nextSibling, root.firstChild.nextSibling);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "self insertBefore lastChild";
mutateCount = 0;
root.insertBefore(root.lastChild, root.lastChild);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "appendChild last";
mutateCount = 0;
root.appendChild(root.lastChild);
check();
is(mutateCount, 2, "should remove and reinsert " + testName);
testName = "prepare script/style";
script = document.createElement("script");
script.appendChild(document.createTextNode("void(0);"));

View File

@ -485,6 +485,11 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
rv = file->GetName(filename16);
NS_ENSURE_SUCCESS(rv, rv);
}
if (filename16.IsEmpty()) {
filename16.AssignLiteral("blob");
}
rv = EncodeVal(filename16, filename, true);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -108,7 +108,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLLIElement)
NS_IMPL_STRING_ATTR(nsHTMLLIElement, Type, type)
NS_IMPL_INT_ATTR(nsHTMLLIElement, Value, value)
// values that are handled case-insensitively
static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = {
{ "disc", NS_STYLE_LIST_STYLE_DISC },
{ "circle", NS_STYLE_LIST_STYLE_CIRCLE },
@ -117,11 +117,12 @@ static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = {
{ 0 }
};
// values that are handled case-sensitively
static const nsAttrValue::EnumTable kOrderedListItemTypeTable[] = {
{ "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA },
{ "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA },
{ "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN },
{ "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN },
{ "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA },
{ "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA },
{ "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN },
{ "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN },
{ "1", NS_STYLE_LIST_STYLE_DECIMAL },
{ 0 }
};

View File

@ -148,7 +148,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Compact, compact)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSharedListElement, Start, start, 1)
NS_IMPL_STRING_ATTR(nsHTMLSharedListElement, Type, type)
// Shared with nsHTMLSharedElement.cpp
nsAttrValue::EnumTable kListTypeTable[] = {
{ "none", NS_STYLE_LIST_STYLE_NONE },
{ "disc", NS_STYLE_LIST_STYLE_DISC },
@ -163,12 +163,12 @@ nsAttrValue::EnumTable kListTypeTable[] = {
{ 0 }
};
nsAttrValue::EnumTable kOldListTypeTable[] = {
{ "1", NS_STYLE_LIST_STYLE_OLD_DECIMAL },
{ "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA },
{ "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA },
{ "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN },
{ "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN },
static const nsAttrValue::EnumTable kOldListTypeTable[] = {
{ "1", NS_STYLE_LIST_STYLE_DECIMAL },
{ "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA },
{ "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA },
{ "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN },
{ "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN },
{ 0 }
};

View File

@ -216,8 +216,7 @@ _TEST_FILES = \
test_bug555840.html \
test_bug561636.html \
test_bug590363.html \
test_bug557628-1.html \
test_bug557628-2.html \
test_bug557628.html \
test_bug592802.html \
test_bug595429.html \
test_bug595447.html \

View File

@ -20,6 +20,72 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=551670
/** Test for Bug 551670 **/
// TODO: maybe make those reflections be tested against all input types.
// .accept
reflectString(document.createElement("input"), "accept",
[ "audio/*", "video/*", "image/*", "image/png",
"application/msword", "appplication/pdf" ]);
// .alt
reflectString(document.createElement("input"), "alt");
// .autocomplete
reflectLimitedEnumerated(document.createElement("input"), "autocomplete",
[ "on", "off" ], [ "", "default", "foo", "tulip" ]);
// TODO: autofocus (boolean)
// TODO: defaultChecked (boolean)
// TODO: checked (boolean)
// TODO: dirName (not implemented)
// TODO: disabled (boolean)
// TODO: form (HTMLFormElement)
// TODO: files (FileList)
// TODO: formAction (URL)
// .formEnctype
reflectLimitedEnumerated(document.createElement("input"), "formEnctype",
[ "application/x-www-form-urlencoded",
"multipart/form-data", "text/plain" ],
[ "", "foo", "tulip", "multipart/foo" ],
"application/x-www-form-urlencoded");
// .formMethod
reflectLimitedEnumerated(document.createElement("input"), "formMethod",
[ "get", "post" ], [ "", "foo", "tulip" ], "get");
// TODO: formNoValidate (boolean)
// .formTarget
reflectString(document.createElement("input"), "formTarget",
[ "_blank", "_self", "_parent", "_top" ]);
// TODO: height (non-negative integer)
// TODO: indeterminate (boolean)
// TODO: list (HTMLElement)
// TODO: max (not implemented)
// TODO: maxLength (long)
// TODO: min (not implemented)
// TODO: multiple (boolean)
// .name
reflectString(document.createElement("input"), "name",
[ "isindex", "_charset_" ]);
// .pattern
reflectString(document.createElement("input"), "pattern",
[ "[0-9][A-Z]{3}" ]);
// .placeholder
reflectString(document.createElement("input"), "placeholder",
[ "foo\nbar", "foo\rbar", "foo\r\nbar" ]);
// TODO: readOnly (boolean)
// TODO: required (boolean)
// TODO: size (unsigned long)
// TODO: src (URL)
// TODO: step (not implemented)
// .type
reflectLimitedEnumerated(document.createElement("input"),
"type",
@ -31,6 +97,17 @@ reflectLimitedEnumerated(document.createElement("input"),
[ "datetime", "date", "month", "week", "time",
"datetime-local", "number", "range", "color" ]);
// TODO: defaultValue (reflects @value)
// .value doesn't reflect a content attribute.
// TODO: valueAsDate (not implemented)
// TODO: valueAsNumber (not implemented)
// TODO: selectedOption (not implemented)
// TODO: width (non-negative integer)
// .willValidate doesn't reflect a content attribute.
// .validity doesn't reflect a content attribute.
// .validationMessage doesn't reflect a content attribute.
// .labels doesn't reflect a content attribute.
</script>
</pre>
</body>

View File

@ -33,34 +33,6 @@ function invalidEventHandler(e)
gInvalid = true;
}
function checkPatternAttribute(element)
{
ok('pattern' in element, "Element should have the pattern attribute");
is(element.pattern, "tulip",
"pattern IDL attribute value should be 'tulip'");
is(element.getAttribute('pattern'), "tulip",
"pattern content attribute value should be 'tulip'");
element.pattern = "foo";
is(element.pattern, "foo",
"pattern IDL attribute value should be 'foo'");
is(element.getAttribute('pattern'), "foo",
"pattern content attribute value should be 'foo'");
element.removeAttribute('pattern');
ok(!element.pattern,
"Element pattern attribute shouldn't be specified");
is(element.getAttribute('pattern'), null,
"Element pattern attribute shouldn't be specified");
element.setAttribute("pattern", "bar");
is(element.pattern, "bar",
"pattern IDL attribute value should be 'bar'");
is(element.getAttribute('pattern'), "bar",
"pattern content attribute value should be 'bar'");
}
function completeValidityCheck(element, alwaysValid, isBarred)
{
if (element.type == 'file') {
@ -286,9 +258,6 @@ function checkPatternValidity(element)
var input = document.getElementById('i');
// All input types should have the pattern attribute.
checkPatternAttribute(input);
// |validTypes| are the types which accept @pattern
// and |invalidTypes| are the ones which do not accept it.
var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url');

View File

@ -1,3 +1,107 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* reflect.js is a collection of methods to test HTML attribute reflection.
* Each of attribute is reflected differently, depending on various parameters,
* see:
* http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
*
* Do not forget to add these line at the beginning of each new reflect* method:
* ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
* is(typeof aElement[aAttr], <type>, aAttr + " IDL attribute should be a <type>");
*/
/**
* Checks that a given attribute is correctly reflected as a string.
*
* @param aElement Element node to test
* @param aAttr String name of the attribute
* @param aOtherValues Array other values to test in addition of the default ones [optional]
*/
function reflectString(aElement, aAttr, aOtherValues)
{
var otherValues = aOtherValues !== undefined ? aOtherValues : [];
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
// Tests when the attribute isn't set.
is(aElement.getAttribute(aAttr), null,
"When not set, the content attribute should be undefined.");
is(aElement[aAttr], "",
"When not set, the IDL attribute should return the empty string");
/**
* TODO: as long as null stringification doesn't fallow the webidl specs,
* don't add it to the loop below and keep it here.
*/
aElement.setAttribute(aAttr, null);
todo_is(aElement.getAttribute(aAttr), "null",
"null should have been stringified to 'null'");
todo_is(aElement[aAttr], "null",
"null should have been stringified to 'null'");
aElement.removeAttribute(aAttr);
aElement[aAttr] = null;
todo_is(aElement.getAttribute(aAttr), "null",
"null should have been stringified to 'null'");
todo_is(aElement[aAttr], "null",
"null should have been stringified to 'null'");
aElement.removeAttribute(aAttr);
// Tests various strings.
var stringsToTest = [
// [ test value, expected result ]
[ "", "" ],
[ "null", "null" ],
[ "undefined", "undefined" ],
[ "foo", "foo" ],
[ aAttr, aAttr ],
// TODO: uncomment this when null stringification will follow the specs.
// [ null, "null" ],
[ undefined, "undefined" ],
[ true, "true" ],
[ false, "false" ],
[ 42, "42" ],
// ES5, verse 8.12.8.
[ { toString: function() { return "foo" } },
"foo" ],
[ { valueOf: function() { return "foo" } },
"[object Object]" ],
[ { valueOf: function() { return "quux" },
toString: undefined },
"quux" ],
[ { valueOf: function() { return "foo" },
toString: function() { return "bar" } },
"bar" ]
];
otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
stringsToTest.forEach(function([v, r]) {
aElement.setAttribute(aAttr, v);
is(aElement[aAttr], r,
"IDL attribute should return the value it has been set to.");
is(aElement.getAttribute(aAttr), r,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
aElement[aAttr] = v;
is(aElement[aAttr], r,
"IDL attribute should return the value it has been set to.");
is(aElement.getAttribute(aAttr), r,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
});
// Tests after removeAttribute() is called. Should be equivalent with not set.
is(aElement.getAttribute(aAttr), null,
"When not set, the content attribute should be undefined.");
is(aElement[aAttr], "",
"When not set, the IDL attribute should return the empty string");
}
/**
* Checks that a given attribute name for a given element is correctly reflected
* as an unsigned int.
@ -19,6 +123,9 @@ function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
}
}
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "number", aAttr + " IDL attribute should be a string");
// Check default value.
is(aElement[aAttr], aDefault, "default value should be " + aDefault);
ok(!aElement.hasAttribute(aAttr), aAttr + " shouldn't be present");
@ -108,6 +215,10 @@ function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
var defaultValue = aDefaultValue !== undefined ? aDefaultValue : "";
var unsupportedValues = aUnsupportedValues !== undefined ? aUnsupportedValues
: [];
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
// Explicitly check the default value.
aElement.removeAttribute(aAttr);
is(aElement[aAttr], defaultValue,
@ -126,7 +237,7 @@ function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
is(aElement[aAttr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
"Content attribute should be upper-cased.");
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
aElement[aAttr] = v;
@ -140,7 +251,7 @@ function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
is(aElement[aAttr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
"Content attribute should be upper-cased.");
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
});
@ -175,7 +286,7 @@ function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
todo_is(aElement[aAttr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
"Content attribute should be upper-cased.");
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
aElement[aAttr] = v;
@ -189,7 +300,7 @@ function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
todo_is(aElement[aAttr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
"Content attribute should be upper-cased.");
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
});
}

View File

@ -13,8 +13,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=457800
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=457800">Mozilla Bug 457800</a>
<p id="display"></p>
<div id="content" style="display: none">
<input type="text" id="inputtext"/><br/>
<input type="password"id="inputpassword"/><br/>
<textarea id="textarea"></textarea>
</div>
<pre id="test">
@ -51,8 +49,6 @@ function testPlaceholderForElement(element)
is(element.getAttribute('placeholder'), 'place\rholder', "\\r shouldn't be stripped");
}
testPlaceholderForElement(document.getElementById('inputtext'));
testPlaceholderForElement(document.getElementById('inputpassword'));
testPlaceholderForElement(document.getElementById('textarea'));
</script>

View File

@ -1,72 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=557628
-->
<head>
<title>Test for Bug 557628</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<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=557628">Mozilla Bug 557628</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 557628 **/
var inputAutocompleteTestData = [
// Default value.
[ "" ],
// Valid values.
[ "on", "off" ],
// Invalid values.
[ "", " ", "foo", "default", "foo bar" ]
];
function checkAttribute(element, name, data)
{
is(element.getAttribute(name), undefined,
"By default " + name + " content attribute should be undefined");
is(element[name], data[0][0],
"By default " + name + " IDL attribute should be equal to " +
data[0][0]);
// Valid values.
for (i in data[1]) {
element.setAttribute(name, data[1][i]);
is(element.getAttribute(name), data[1][i],
"getAttribute should return the content attribute");
is(element[name], data[1][i], "When getting, " + name + " IDL attribute " +
"should be equal to the content attribute if the value is known");
}
// Invalid values.
for (i in data[2]) {
element.setAttribute(name, data[2][i]);
is(element.getAttribute(name), data[2][i],
"getAttribute should return the content attribute");
is(element[name], data[0][0], "When getting, " + name + " IDL attribute " +
"should return the default value if the content attribute value isn't known");
}
// TODO values.
for (i in data[3]) {
element.setAttribute(name, data[3][i]);
is(element.getAttribute(name), data[3][i],
"getAttribute should return the content attribute");
todo_is(element[name], data[3][i], "When getting, " + name + " IDL attribute " +
"should be equal to the content attribute if the value is known");
}
}
var input = document.createElement('input');
checkAttribute(input, 'autocomplete', inputAutocompleteTestData);
</script>
</pre>
</body>
</html>

View File

@ -48,13 +48,10 @@ function checkFormTarget(aElement)
isFormTargetEquals(aElement, "", true);
}
var input = document.createElement('input');
var button = document.createElement('button');
ok('formTarget' in input, "formTarget is a HTMLInputElement property");
ok('formTarget' in button, "formTarget is a HTMLButtonElement property");
checkFormTarget(input);
checkFormTarget(button);
</script>

View File

@ -63,13 +63,10 @@ function checkAttribute(form, attrName, idlName, data)
}
var form = document.createElement('form');
var input = document.createElement('input');
var button = document.createElement('button');
checkAttribute(form, 'enctype', 'enctype', enctypeTestData);
checkAttribute(form, 'method', 'method', methodTestData);
checkAttribute(input, 'formenctype', 'formEnctype', enctypeTestData);
checkAttribute(input, 'formmethod', 'formMethod', methodTestData);
checkAttribute(button, 'formenctype', 'formEnctype', enctypeTestData);
checkAttribute(button, 'formmethod', 'formMethod', methodTestData);

View File

@ -22,19 +22,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=590363
var testData = [
/* type to test | is the value reset when changing to file then reverting */
[ "button", false ],
[ "button", false ],
[ "checkbox", false ],
[ "hidden", false ],
[ "reset", false ],
[ "image", false ],
[ "radio", false ],
[ "submit", false ],
[ "tel", true ],
[ "text", true ],
[ "url", true ],
[ "email", true ],
[ "search", true ],
[ "hidden", false ],
[ "reset", false ],
[ "image", false ],
[ "radio", false ],
[ "submit", false ],
[ "tel", true ],
[ "text", true ],
[ "url", true ],
[ "email", true ],
[ "search", true ],
[ "password", true ],
[ "number", true ],
// 'file' is treated separatly.
];
var todoTypes = [
"datetime", "date", "month", "week", "time", "datetime-local", "range", "color"
];
var length = testData.length;
@ -42,9 +48,17 @@ for (var i=0; i<length; ++i) {
for (var j=0; j<length; ++j) {
var e = document.createElement('input');
e.type = testData[i][0];
e.value = "foo";
var expectedValue;
if (testData[i][0] == 'number' || testData[j][0] == 'number') {
expectedValue = '42';
} else {
expectedValue = "foo";
}
e.value = expectedValue;
e.type = testData[j][0];
is(e.value, "foo", ".value should still return the same value after " +
is(e.value, expectedValue, ".value should still return the same value after " +
"changing type from " + testData[i][0] + " to " + testData[j][0]);
}
}
@ -67,6 +81,13 @@ for each (var data in testData) {
}
}
// TODO checks
for each (var type in todoTypes) {
var e = document.createElement('input');
e.type = type;
todo_is(e.type, type, type + " type isn't supported yet");
}
</script>
</pre>
</body>

View File

@ -1,3 +1,6 @@
<handler event="keypress" key=" " modifiers="shift" command="cmd_scrollPageUp" />
<handler event="keypress" key=" " command="cmd_scrollPageDown" />
<handler event="keypress" keycode="VK_LEFT" command="cmd_charPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" command="cmd_charNext"/>
<handler event="keypress" keycode="VK_LEFT" command="cmd_selectCharPrevious" modifiers="shift"/>

View File

@ -112,6 +112,7 @@ CPPSRCS = \
nsStructuredCloneContainer.cpp \
nsDOMNavigationTiming.cpp \
nsPerformance.cpp \
nsDOMMemoryReporter.cpp \
$(NULL)
include $(topsrcdir)/dom/dom-config.mk

View File

@ -0,0 +1,110 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMMemoryReporter.h"
#include "nsGlobalWindow.h"
nsDOMMemoryReporter::nsDOMMemoryReporter()
{
}
NS_IMPL_ISUPPORTS1(nsDOMMemoryReporter, nsIMemoryReporter)
/* static */
void
nsDOMMemoryReporter::Init()
{
// The memory reporter manager is going to own this object.
NS_RegisterMemoryReporter(new nsDOMMemoryReporter());
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetProcess(char** aProcess)
{
// "" means the main process.
*aProcess = strdup("");
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetPath(char** aMemoryPath)
{
*aMemoryPath = strdup("explicit/dom");
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetKind(int* aKind)
{
*aKind = KIND_HEAP;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetDescription(char** aDescription)
{
*aDescription = strdup("Memory used by the DOM.");
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetUnits(PRInt32* aUnits)
{
*aUnits = UNITS_BYTES;
return NS_OK;
}
static
PLDHashOperator
GetWindowsMemoryUsage(const PRUint64& aId, nsGlobalWindow*& aWindow,
void* aClosure)
{
*(PRInt64*)aClosure += aWindow->SizeOf();
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetAmount(PRInt64* aAmount) {
*aAmount = 0;
nsGlobalWindow::WindowByIdTable* windows = nsGlobalWindow::GetWindowsTable();
windows->Enumerate(GetWindowsMemoryUsage, aAmount);
return NS_OK;
}

View File

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMMemoryReporter_h__
#define nsDOMMemoryReporter_h__
#include "nsIMemoryReporter.h"
class nsDOMMemoryReporter: public nsIMemoryReporter {
public:
NS_DECL_ISUPPORTS
static void Init();
NS_IMETHOD GetProcess(char** aProcess);
NS_IMETHOD GetPath(char** aMemoryPath);
NS_IMETHOD GetKind(int* aKnd);
NS_IMETHOD GetDescription(char** aDescription);
NS_IMETHOD GetUnits(PRInt32* aUnits);
NS_IMETHOD GetAmount(PRInt64* aAmount);
private:
// Protect ctor, use Init() instead.
nsDOMMemoryReporter();
};
#endif // nsDOMMemoryReporter_h__

View File

@ -31,6 +31,7 @@
* Ryan Jones <sciguyryan@gmail.com>
* Jeff Walden <jwalden+code@mit.edu>
* Ben Bucksch <ben.bucksch beonex.com>
* Emanuele Costa <emanuele.costa@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -252,7 +253,7 @@ using mozilla::TimeStamp;
using mozilla::TimeDuration;
nsIDOMStorageList *nsGlobalWindow::sGlobalStorageList = nsnull;
nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sOuterWindowsById = nsnull;
nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nsnull;
static nsIEntropyCollector *gEntropyCollector = nsnull;
static PRInt32 gRefCnt = 0;
@ -887,18 +888,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mObserver = nsnull;
SetIsProxy();
if (!sOuterWindowsById) {
sOuterWindowsById = new WindowByIdTable();
if (!sOuterWindowsById->Init()) {
delete sOuterWindowsById;
sOuterWindowsById = nsnull;
}
}
if (sOuterWindowsById) {
sOuterWindowsById->Put(mWindowID, this);
}
}
// We could have failed the first time through trying
@ -952,17 +941,35 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
PR_LOG(gDOMLeakPRLog, PR_LOG_DEBUG,
("DOMWINDOW %p created outer=%p", this, aOuterWindow));
#endif
// TODO: could be moved to a ::Init() method, see bug 667183.
if (!sWindowsById) {
sWindowsById = new WindowByIdTable();
if (!sWindowsById->Init()) {
delete sWindowsById;
sWindowsById = nsnull;
NS_ERROR("sWindowsById initialization failed!");
}
}
if (sWindowsById) {
NS_ASSERTION(!sWindowsById->Get(mWindowID),
"This window shouldn't be in the hash table yet!");
sWindowsById->Put(mWindowID, this);
}
}
nsGlobalWindow::~nsGlobalWindow()
{
if (sOuterWindowsById) {
sOuterWindowsById->Remove(mWindowID);
// We have to check if sWindowsById isn't null because ::Shutdown might have
// been called.
if (sWindowsById) {
NS_ASSERTION(sWindowsById->Get(mWindowID),
"This window should be in the hash table");
sWindowsById->Remove(mWindowID);
}
if (!--gRefCnt) {
NS_IF_RELEASE(gEntropyCollector);
delete sOuterWindowsById;
sOuterWindowsById = nsnull;
}
#ifdef DEBUG
nsCAutoString url;
@ -1038,6 +1045,9 @@ nsGlobalWindow::ShutDown()
fclose(gDumpFile);
}
gDumpFile = nsnull;
delete sWindowsById;
sWindowsById = nsnull;
}
// static
@ -7474,6 +7484,15 @@ nsGlobalWindow::SetActive(PRBool aActive)
NotifyDocumentTree(mDoc, nsnull);
}
void nsGlobalWindow::SetIsBackground(PRBool aIsBackground)
{
PRBool resetTimers = (!aIsBackground && IsBackground());
nsPIDOMWindow::SetIsBackground(aIsBackground);
if (resetTimers) {
ResetTimersForNonBackgroundWindow();
}
}
void nsGlobalWindow::MaybeUpdateTouchState()
{
FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ());
@ -8839,10 +8858,8 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
}
nsRefPtr<nsTimeout> timeout = new nsTimeout();
if (aIsInterval) {
timeout->mInterval = interval;
}
timeout->mIsInterval = aIsInterval;
timeout->mInterval = interval;
timeout->mScriptHandler = aHandler;
// Now clamp the actual interval we will use for the timer based on
@ -9143,7 +9160,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
++gRunningTimeoutDepth;
++mTimeoutFiringDepth;
PRBool trackNestingLevel = !timeout->mInterval;
PRBool trackNestingLevel = !timeout->mIsInterval;
PRUint32 nestingLevel;
if (trackNestingLevel) {
nestingLevel = sNestingLevel;
@ -9229,7 +9246,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
// If we have a regular interval timer, we re-schedule the
// timeout, accounting for clock drift.
if (timeout->mInterval) {
if (timeout->mIsInterval) {
// Compute time to next timeout for interval timer.
// Make sure nextInterval is at least DOMMinTimeoutValue().
TimeDuration nextInterval =
@ -9300,7 +9317,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
}
if (timeout->mTimer) {
if (timeout->mInterval) {
if (timeout->mIsInterval) {
isInterval = PR_TRUE;
} else {
// The timeout still has an OS timer, and it's not an
@ -9378,7 +9395,7 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID)
/* We're running from inside the timeout. Mark this
timeout for deferred deletion by the code in
RunTimeout() */
timeout->mInterval = 0;
timeout->mIsInterval = PR_FALSE;
}
else {
/* Delete the timeout from the pending timeout list */
@ -9398,6 +9415,94 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID)
return NS_OK;
}
nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
{
FORWARD_TO_INNER(ResetTimersForNonBackgroundWindow, (),
NS_ERROR_NOT_INITIALIZED);
if (IsFrozen() || mTimeoutsSuspendDepth) {
return NS_OK;
}
TimeStamp now = TimeStamp::Now();
for (nsTimeout *timeout = FirstTimeout(); IsTimeout(timeout); ) {
// It's important that this check be <= so that we guarantee that
// taking NS_MAX with |now| won't make a quantity equal to
// timeout->mWhen below.
if (timeout->mWhen <= now) {
timeout = timeout->Next();
continue;
}
if (timeout->mWhen - now >
TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)) {
// No need to loop further. Timeouts are sorted in mWhen order
// and the ones after this point were all set up for at least
// gMinBackgroundTimeoutValue ms and hence were not clamped.
break;
}
/* We switched from background. Re-init the timer appropriately */
// Compute the interval the timer should have had if it had not been set in a
// background window
TimeDuration interval =
TimeDuration::FromMilliseconds(NS_MAX(timeout->mInterval,
PRUint32(DOMMinTimeoutValue())));
PRUint32 oldIntervalMillisecs = 0;
timeout->mTimer->GetDelay(&oldIntervalMillisecs);
TimeDuration oldInterval = TimeDuration::FromMilliseconds(oldIntervalMillisecs);
if (oldInterval > interval) {
// unclamp
TimeStamp firingTime =
NS_MAX(timeout->mWhen - oldInterval + interval, now);
NS_ASSERTION(firingTime < timeout->mWhen,
"Our firing time should strictly decrease!");
TimeDuration delay = firingTime - now;
timeout->mWhen = firingTime;
// Since we reset mWhen we need to move |timeout| to the right
// place in the list so that it remains sorted by mWhen.
// Get the pointer to the next timeout now, before we move the
// current timeout in the list.
nsTimeout* nextTimeout = timeout->Next();
// It is safe to remove and re-insert because mWhen is now
// strictly smaller than it used to be, so we know we'll insert
// |timeout| before nextTimeout.
NS_ASSERTION(!IsTimeout(nextTimeout) ||
timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
PR_REMOVE_LINK(timeout);
// InsertTimeoutIntoList will addref |timeout| and reset
// mFiringDepth. Make sure to undo that after calling it.
PRUint32 firingDepth = timeout->mFiringDepth;
InsertTimeoutIntoList(timeout);
timeout->mFiringDepth = firingDepth;
timeout->Release();
nsresult rv =
timeout->mTimer->InitWithFuncCallback(TimerCallback,
timeout,
delay.ToMilliseconds(),
nsITimer::TYPE_ONE_SHOT);
if (NS_FAILED(rv)) {
NS_WARNING("Error resetting non background timer for DOM timeout!");
return rv;
}
timeout = nextTimeout;
} else {
timeout = timeout->Next();
}
}
return NS_OK;
}
// A JavaScript specific version.
nsresult
nsGlobalWindow::ClearTimeoutOrInterval()

View File

@ -195,10 +195,13 @@ struct nsTimeout : PRCList
// True if this is one of the timeouts that are currently running
PRPackedBool mRunning;
// True if this is a repeating/interval timer
PRPackedBool mIsInterval;
// Returned as value of setTimeout()
PRUint32 mPublicId;
// Non-zero interval in milliseconds if repetitive timeout
// Interval in milliseconds
PRUint32 mInterval;
// mWhen and mTimeRemaining can't be in a union, sadly, because they
@ -287,6 +290,7 @@ public:
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
// public methods
nsPIDOMWindow* GetPrivateParent();
@ -341,6 +345,7 @@ public:
virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
virtual NS_HIDDEN_(void) ActivateOrDeactivate(PRBool aActivate);
virtual NS_HIDDEN_(void) SetActive(PRBool aActive);
virtual NS_HIDDEN_(void) SetIsBackground(PRBool aIsBackground);
virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler);
virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
@ -531,13 +536,28 @@ public:
}
static nsGlobalWindow* GetOuterWindowWithId(PRUint64 aWindowID) {
return sOuterWindowsById ? sOuterWindowsById->Get(aWindowID) : nsnull;
nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nsnull;
}
static bool HasIndexedDBSupport();
static bool HasPerformanceSupport();
static WindowByIdTable* GetWindowsTable() {
return sWindowsById;
}
PRInt64 SizeOf() const {
PRInt64 size = sizeof(*this);
if (IsInnerWindow() && mDoc) {
size += mDoc->SizeOf();
}
return size;
}
private:
// Enable updates for the accelerometer.
void EnableDeviceMotionUpdates();
@ -648,6 +668,7 @@ protected:
// JS specific timeout functions (JS args grabbed from context).
nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn);
nsresult ClearTimeoutOrInterval();
nsresult ResetTimersForNonBackgroundWindow();
// The timeout implementation functions.
void RunTimeout(nsTimeout *aTimeout);
@ -959,8 +980,7 @@ protected:
friend class PostMessageEvent;
static nsIDOMStorageList* sGlobalStorageList;
typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
static WindowByIdTable* sOuterWindowsById;
static WindowByIdTable* sWindowsById;
};
/*

View File

@ -105,7 +105,7 @@ public:
return mIsActive;
}
void SetIsBackground(PRBool aIsBackground)
virtual void SetIsBackground(PRBool aIsBackground)
{
mIsBackground = aIsBackground;
}

View File

@ -79,6 +79,10 @@ interface nsIDOMCanvasRenderingContext2D : nsISupports
void translate(in float x, in float y);
void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
void setTransform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
[implicit_jscontext]
attribute jsval mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
[implicit_jscontext]
attribute jsval mozCurrentTransformInverse;
// compositing
attribute float globalAlpha; /* default 1.0 -- opaque */
@ -117,6 +121,10 @@ enum CanvasMultiGetterType {
attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
attribute float miterLimit; /* default 10 */
[implicit_jscontext]
attribute jsval mozDash; /* default |null| */
attribute float mozDashOffset; /* default 0.0 */
// shadows
attribute float shadowOffsetX;
attribute float shadowOffsetY;

View File

@ -298,42 +298,92 @@ ContentChild::AllocPMemoryReportRequest()
return new MemoryReportRequestChild();
}
// This is just a wrapper for InfallibleTArray<MemoryReport> that implements
// nsISupports, so it can be passed to nsIMemoryMultiReporter::CollectReports.
class MemoryReportsWrapper : public nsISupports {
public:
NS_DECL_ISUPPORTS
MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { }
InfallibleTArray<MemoryReport> *mReports;
};
NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
class MemoryReportCallback : public nsIMemoryMultiReporterCallback
{
public:
NS_DECL_ISUPPORTS
MemoryReportCallback(const nsACString &aProcess)
: mProcess(aProcess)
{
}
NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
PRInt32 aKind, PRInt32 aUnits, PRInt64 aAmount,
const nsACString &aDescription,
nsISupports *aiWrappedReports)
{
MemoryReportsWrapper *wrappedReports =
static_cast<MemoryReportsWrapper *>(aiWrappedReports);
MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
aAmount, nsCString(aDescription));
wrappedReports->mReports->AppendElement(memreport);
return NS_OK;
}
private:
const nsCString mProcess;
};
NS_IMPL_ISUPPORTS1(
MemoryReportCallback
, nsIMemoryMultiReporterCallback
)
bool
ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child)
{
InfallibleTArray<MemoryReport> reports;
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
nsCOMPtr<nsISimpleEnumerator> r;
mgr->EnumerateReporters(getter_AddRefs(r));
InfallibleTArray<MemoryReport> reports;
static const int maxLength = 31; // big enough; pid is only a few chars
nsPrintfCString process(maxLength, "Content (%d)", getpid());
// First do the vanilla memory reporters.
nsCOMPtr<nsISimpleEnumerator> e;
mgr->EnumerateReporters(getter_AddRefs(e));
PRBool more;
while (NS_SUCCEEDED(r->HasMoreElements(&more)) && more) {
nsCOMPtr<nsIMemoryReporter> report;
r->GetNext(getter_AddRefs(report));
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
nsCOMPtr<nsIMemoryReporter> r;
e->GetNext(getter_AddRefs(r));
nsCString path;
PRInt32 kind;
PRInt32 units;
nsCString desc;
PRInt64 amount;
report->GetPath(getter_Copies(path));
report->GetKind(&kind);
report->GetUnits(&units);
report->GetAmount(&amount);
report->GetDescription(getter_Copies(desc));
static const int maxLength = 31; // big enough; pid is only a few chars
MemoryReport memreport(nsPrintfCString(maxLength, "Content (%d)",
getpid()),
path,
kind,
units,
amount,
desc);
nsCString desc;
r->GetPath(getter_Copies(path));
r->GetKind(&kind);
r->GetUnits(&units);
r->GetAmount(&amount);
r->GetDescription(getter_Copies(desc));
MemoryReport memreport(process, path, kind, units, amount, desc);
reports.AppendElement(memreport);
}
// Then do the memory multi-reporters, by calling CollectReports on each
// one, whereupon the callback will turn each measurement into a
// MemoryReport.
mgr->EnumerateMultiReporters(getter_AddRefs(e));
MemoryReportsWrapper wrappedReports(&reports);
MemoryReportCallback cb(process);
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
nsCOMPtr<nsIMemoryMultiReporter> r;
e->GetNext(getter_AddRefs(r));
r->CollectReports(&cb, &wrappedReports);
}
child->Send__delete__(child, reports);

View File

@ -514,8 +514,10 @@ bool
TabParent::RecvGetIMEEnabled(PRUint32* aValue)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
if (!widget) {
*aValue = nsIWidget::IME_STATUS_DISABLED;
return true;
}
IMEContext context;
widget->GetInputMode(context);

View File

@ -4934,8 +4934,9 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
NS_ENSURE_SUCCESS(res, res);
}
}
if (emptyBlock)
nsCOMPtr<nsIContent> emptyContent = do_QueryInterface(emptyBlock);
if (emptyBlock && emptyContent->IsEditable())
{
nsCOMPtr<nsIDOMNode> blockParent;
PRInt32 offset;

View File

@ -52,6 +52,7 @@ _TEST_FILES = \
test_bug372345.html \
test_bug410986.html \
test_bug432225.html \
test_bug439808.html \
test_bug455992.html \
test_bug456244.html \
test_bug478725.html \
@ -61,6 +62,8 @@ _TEST_FILES = \
test_bug520189.html \
test_bug525389.html \
test_bug537046.html \
test_bug549262.html \
file_bug549262.html \
test_bug550434.html \
test_bug551704.html \
test_bug592592.html \

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<body>
<a href="">test</a>
<div id="editor" contenteditable="true">abc</div>
<div style="height: 20000px;"></div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=439808
-->
<head>
<title>Test for Bug 439808</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<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=439808">Mozilla Bug 439808</a>
<p id="display"></p>
<div id="content">
<span><span contenteditable id="e">twest</span></span>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 439808 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var e = document.getElementById("e");
e.focus();
getSelection().collapse(e.firstChild, 1);
synthesizeKey("VK_DELETE", {});
is(e.textContent, "test", "Delete key worked");
synthesizeKey("VK_BACK_SPACE", {});
is(e.textContent, "est", "Backspace key worked");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=549262
-->
<head>
<title>Test for Bug 549262</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549262">Mozilla Bug 549262</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 549262 **/
SimpleTest.waitForExplicitFinish();
var win = window.open("file_bug549262.html", "_blank",
"width=600,height=600");
SimpleTest.waitForFocus(function() {
// Make sure that pressing Space when a contenteditable element is not focused
// will scroll the page.
var ed = win.document.getElementById("editor");
var sc = win.document.querySelector("a");
sc.focus();
is(win.scrollY, 0, "Sanity check");
synthesizeKey(" ", {}, win);
setTimeout(function() {
isnot(win.scrollY, 0, "Page is scrolled down");
is(ed.textContent, "abc", "The content of the editable element has not changed");
synthesizeKey(" ", {shiftKey: true}, win);
setTimeout(function() {
is(win.scrollY, 0, "Page is scrolled up");
is(ed.textContent, "abc", "The content of the editable element has not changed");
// Make sure that pressing Space when a contenteditable element is focused
// will not scroll the page, and will edit the element.
ed.focus();
win.getSelection().collapse(ed.firstChild, 1);
synthesizeKey(" ", {}, win);
setTimeout(function() {
is(win.scrollY, 0, "Page is not scrolled down");
is(ed.textContent, "a bc", "The content of the editable element has changed");
sc.focus();
synthesizeKey(" ", {}, win);
setTimeout(function() {
isnot(win.scrollY, 0, "Page is scrolled down");
is(ed.textContent, "a bc", "The content of the editable element has not changed");
ed.focus();
win.getSelection().collapse(ed.firstChild, 3);
synthesizeKey(" ", {shiftKey: true}, win);
setTimeout(function() {
isnot(win.scrollY, 0, "Page is not scrolled up");
is(ed.textContent, "a b c", "The content of the editable element has changed");
win.close();
SimpleTest.finish();
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
}, win);
</script>
</pre>
</body>
</html>

View File

@ -107,20 +107,38 @@ struct DrawOptions {
* mLineJoin - Join style used for joining lines.
* mLineCap - Cap style used for capping lines.
* mMiterLimit - Miter limit in units of linewidth
* mDashPattern - Series of on/off userspace lengths defining dash.
* Owned by the caller; must live at least as long as
* this StrokeOptions.
* mDashPattern != null <=> mDashLength > 0.
* mDashLength - Number of on/off lengths in mDashPattern.
* mDashOffset - Userspace offset within mDashPattern at which stroking
* begins.
*/
struct StrokeOptions {
StrokeOptions(Float aLineWidth = 1.0f,
JoinStyle aLineJoin = JOIN_MITER_OR_BEVEL,
CapStyle aLineCap = CAP_BUTT,
Float aMiterLimit = 10.0f)
Float aMiterLimit = 10.0f,
size_t aDashLength = 0,
const Float* aDashPattern = 0,
Float aDashOffset = 0.f)
: mLineWidth(aLineWidth)
, mMiterLimit(aMiterLimit)
, mDashPattern(aDashLength > 0 ? aDashPattern : 0)
, mDashLength(aDashLength)
, mDashOffset(aDashOffset)
, mLineJoin(aLineJoin)
, mLineCap(aLineCap)
{}
{
MOZ_ASSERT(aDashLength == 0 || aDashPattern);
}
Float mLineWidth;
Float mMiterLimit;
const Float* mDashPattern;
size_t mDashLength;
Float mDashOffset;
JoinStyle mLineJoin : 4;
CapStyle mLineCap : 3;
};

View File

@ -65,6 +65,8 @@ typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
__out ID3D10Effect **ppEffect
);
using namespace std;
namespace mozilla {
namespace gfx {
@ -665,8 +667,10 @@ DrawTargetD2D::CopySurface(SourceSurface *aSurface,
const IntRect &aSourceRect,
const IntPoint &aDestination)
{
Rect srcRect(aSourceRect.x, aSourceRect.y, aSourceRect.width, aSourceRect.height);
Rect dstRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height);
Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y),
Float(aSourceRect.width), Float(aSourceRect.height));
Rect dstRect(Float(aDestination.x), Float(aDestination.y),
Float(aSourceRect.width), Float(aSourceRect.height));
mRT->SetTransform(D2D1::IdentityMatrix());
mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED);
@ -1632,10 +1636,36 @@ DrawTargetD2D::CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
}
HRESULT hr = factory()->CreateStrokeStyle(D2D1::StrokeStyleProperties(capStyle, capStyle,
capStyle, joinStyle,
aStrokeOptions.mMiterLimit),
NULL, 0, byRef(style));
HRESULT hr;
if (aStrokeOptions.mDashPattern) {
typedef vector<Float> FloatVector;
// D2D "helpfully" multiplies the dash pattern by the line width.
// That's not what cairo does, or is what <canvas>'s dash wants.
// So fix the multiplication in advance.
Float lineWidth = aStrokeOptions.mLineWidth;
FloatVector dash(aStrokeOptions.mDashPattern,
aStrokeOptions.mDashPattern + aStrokeOptions.mDashLength);
for (FloatVector::iterator it = dash.begin(); it != dash.end(); ++it) {
*it /= lineWidth;
}
hr = factory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties(capStyle, capStyle,
capStyle, joinStyle,
aStrokeOptions.mMiterLimit,
D2D1_DASH_STYLE_CUSTOM,
aStrokeOptions.mDashOffset),
&dash[0], // data() is not C++98, although it's in recent gcc
// and VC10's STL
dash.size(),
byRef(style));
} else {
hr = factory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties(capStyle, capStyle,
capStyle, joinStyle,
aStrokeOptions.mMiterLimit),
NULL, 0, byRef(style));
}
if (FAILED(hr)) {
gfxWarning() << "Failed to create Direct2D stroke style.";

View File

@ -40,6 +40,7 @@
#include <string>
#include <sstream>
#include <stdio.h>
#include "Point.h"

View File

@ -545,7 +545,28 @@ gfxContext::SetDash(gfxFloat *dashes, int ndash, gfxFloat offset)
{
cairo_set_dash(mCairo, dashes, ndash, offset);
}
//void getDash() const;
bool
gfxContext::CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const
{
int count = cairo_get_dash_count(mCairo);
if (count <= 0 || !dashes.SetLength(count)) {
return false;
}
cairo_get_dash(mCairo, dashes.Elements(), offset);
return true;
}
gfxFloat
gfxContext::CurrentDashOffset() const
{
if (cairo_get_dash_count(mCairo) <= 0) {
return 0.0;
}
gfxFloat offset;
cairo_get_dash(mCairo, NULL, &offset);
return offset;
}
void
gfxContext::SetLineWidth(gfxFloat width)

View File

@ -51,6 +51,7 @@
#include "nsISupportsImpl.h"
typedef struct _cairo cairo_t;
template <typename T> class FallibleTArray;
/**
* This is the main class for doing actual drawing. It is initialized using
@ -465,7 +466,12 @@ public:
void SetDash(gfxLineType ltype);
void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset);
//void getDash() const;
// Return true if dashing is set, false if it's not enabled or the
// context is in an error state. |offset| can be NULL to mean
// "don't care".
bool CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const;
// Returns 0.0 if dashing isn't enabled.
gfxFloat CurrentDashOffset() const;
/**
* Sets the line width that's used for line drawing.

View File

@ -4446,7 +4446,7 @@ dnl ========================================================
dnl Defaults
case "${target}" in
arm-android-eabi)
arm-android*|arm-linuxandroid*)
MOZ_THUMB=yes
MOZ_ARCH=armv7-a
MOZ_FPU=vfp

View File

@ -617,11 +617,6 @@ struct JSRuntime {
JSWrapObjectCallback wrapObjectCallback;
JSPreWrapCallback preWrapObjectCallback;
#ifdef JS_METHODJIT
/* This measures the size of JITScripts, native maps and IC structs. */
size_t mjitDataSize;
#endif
/*
* To ensure that cx->malloc does not cause a GC, we set this flag during
* OOM reporting (in js_ReportOutOfMemory). If a GC is requested while

View File

@ -2729,40 +2729,14 @@ TraceRuntime(JSTracer *trc)
MarkRuntime(trc);
}
static void
IterateCompartmentCells(JSContext *cx, JSCompartment *comp, uint64 traceKindMask,
void *data, IterateCallback callback)
{
for (unsigned thingKind = 0; thingKind < FINALIZE_LIMIT; thingKind++) {
size_t traceKind = GetFinalizableTraceKind(thingKind);
if (traceKindMask && !TraceKindInMask(traceKind, traceKindMask))
continue;
size_t thingSize = GCThingSizeMap[thingKind];
ArenaHeader *aheader = comp->arenas[thingKind].getHead();
for (; aheader; aheader = aheader->next) {
Arena *a = aheader->getArena();
FreeSpan firstSpan(aheader->getFirstFreeSpan());
FreeSpan *span = &firstSpan;
for (uintptr_t thing = a->thingsStart(thingSize);; thing += thingSize) {
JS_ASSERT(thing <= a->thingsEnd());
if (thing == span->start) {
if (!span->hasNext())
break;
thing = span->end;
span = span->nextSpan();
} else {
(*callback)(cx, data, traceKind, reinterpret_cast<void *>(thing));
}
}
}
}
}
void
IterateCells(JSContext *cx, JSCompartment *comp, uint64 traceKindMask,
void *data, IterateCallback callback)
IterateCompartmentsArenasCells(JSContext *cx, void *data,
IterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
{
CHECK_REQUEST(cx);
LeaveTrace(cx);
JSRuntime *rt = cx->runtime;
@ -2776,11 +2750,35 @@ IterateCells(JSContext *cx, JSCompartment *comp, uint64 traceKindMask,
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
if (comp) {
IterateCompartmentCells(cx, comp, traceKindMask, data, callback);
} else {
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
IterateCompartmentCells(cx, *c, traceKindMask, data, callback);
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
JSCompartment *compartment = *c;
(*compartmentCallback)(cx, data, compartment);
for (unsigned thingKind = 0; thingKind < FINALIZE_LIMIT; thingKind++) {
size_t traceKind = GetFinalizableTraceKind(thingKind);
size_t thingSize = GCThingSizeMap[thingKind];
ArenaHeader *aheader = compartment->arenas[thingKind].getHead();
for (; aheader; aheader = aheader->next) {
Arena *arena = aheader->getArena();
(*arenaCallback)(cx, data, arena, traceKind, thingSize);
FreeSpan firstSpan(aheader->getFirstFreeSpan());
FreeSpan *span = &firstSpan;
for (uintptr_t thing = arena->thingsStart(thingSize); ; thing += thingSize) {
JS_ASSERT(thing <= arena->thingsEnd());
if (thing == span->start) {
if (!span->hasNext())
break;
thing = span->end;
span = span->nextSpan();
} else {
(*cellCallback)(cx, data, reinterpret_cast<void *>(thing), traceKind,
thingSize);
}
}
}
}
}
}

View File

@ -1332,30 +1332,22 @@ struct GCMarker : public JSTracer {
void
MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
static inline uint64
TraceKindMask(unsigned kind)
{
return uint64(1) << kind;
}
static inline bool
TraceKindInMask(unsigned kind, uint64 mask)
{
return !!(mask & TraceKindMask(kind));
}
typedef void (*IterateCallback)(JSContext *cx, void *data, size_t traceKind, void *obj);
typedef void (*IterateCompartmentCallback)(JSContext *cx, void *data, JSCompartment *compartment);
typedef void (*IterateArenaCallback)(JSContext *cx, void *data, gc::Arena *arena, size_t traceKind,
size_t thingSize);
typedef void (*IterateCellCallback)(JSContext *cx, void *data, void *thing, size_t traceKind,
size_t thingSize);
/*
* This function calls |callback| on every cell in the GC heap. If |comp| is
* non-null, then it only selects cells in that compartment. If |traceKindMask|
* is non-zero, then only cells whose traceKind belongs to the mask will be
* selected. The mask should be constructed by ORing |TraceKindMask(...)|
* results.
* This function calls |compartmentCallback| on every compartment,
* |arenaCallback| on every in-use arena, and |cellCallback| on every in-use
* cell in the GC heap.
*/
extern JS_FRIEND_API(void)
IterateCells(JSContext *cx, JSCompartment *comp, uint64 traceKindMask,
void *data, IterateCallback callback);
IterateCompartmentsArenasCells(JSContext *cx, void *data,
IterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback);
} /* namespace js */

View File

@ -575,6 +575,9 @@ struct JSScript {
return JITScript_Invalid;
return JITScript_Valid;
}
// This method is implemented in MethodJIT.h.
JS_FRIEND_API(size_t) jitDataSize();/* Size of the JITScript and all sections */
#endif
JS_FRIEND_API(size_t) totalSize(); /* Size of the JSScript and all sections */

View File

@ -816,9 +816,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
*jitp = jit;
/* We tolerate a race in the stats. */
cx->runtime->mjitDataSize += dataSize;
return Compile_Okay;
}

View File

@ -875,6 +875,17 @@ mjit::JITScript::~JITScript()
#endif
}
size_t
JSScript::jitDataSize()
{
size_t n = 0;
if (jitNormal)
n += jitNormal->scriptDataSize();
if (jitCtor)
n += jitCtor->scriptDataSize();
return n;
}
/* Please keep in sync with Compiler::finishThisUp! */
size_t
mjit::JITScript::scriptDataSize()
@ -905,8 +916,6 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
JITScript *jscr;
if ((jscr = script->jitNormal)) {
cx->runtime->mjitDataSize -= jscr->scriptDataSize();
jscr->~JITScript();
cx->free_(jscr);
script->jitNormal = NULL;
@ -914,8 +923,6 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
}
if ((jscr = script->jitCtor)) {
cx->runtime->mjitDataSize -= jscr->scriptDataSize();
jscr->~JITScript();
cx->free_(jscr);
script->jitCtor = NULL;

View File

@ -4715,7 +4715,18 @@ JSBool
MJitDataStats(JSContext *cx, uintN argc, jsval *vp)
{
#ifdef JS_METHODJIT
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(cx->runtime->mjitDataSize));
JSRuntime *rt = cx->runtime;
AutoLockGC lock(rt);
size_t n = 0;
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
for (JSScript *script = (JSScript *)(*c)->scripts.next;
&script->links != &(*c)->scripts;
script = (JSScript *)script->links.next)
{
n += script->jitDataSize();
}
}
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
#else
JS_SET_RVAL(cx, vp, JSVAL_VOID);
#endif

View File

@ -265,10 +265,10 @@ GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
} else
#endif
{
char line[256];
char line[256] = { '\0' };
fputs(prompt, gOutFile);
fflush(gOutFile);
if (!fgets(line, sizeof line, file))
if (!fgets(line, sizeof line, file) && errno != EINTR || feof(file))
return JS_FALSE;
strcpy(bufp, line);
}

View File

@ -1259,29 +1259,21 @@ protected:
static XPConnectGCChunkAllocator gXPCJSChunkAllocator;
#ifdef MOZ_MEMORY
#define JS_GC_HEAP_KIND KIND_HEAP
#define JS_GC_HEAP_KIND nsIMemoryReporter::KIND_HEAP
#else
#define JS_GC_HEAP_KIND KIND_MAPPED
#define JS_GC_HEAP_KIND nsIMemoryReporter::KIND_MAPPED
#endif
// We have per-compartment GC heap totals, so we can't put the total GC heap
// size in the explicit allocations tree. But it's a useful figure, so put it
// in the "others" list.
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
"explicit/js/gc-heap",
JS_GC_HEAP_KIND,
UNITS_BYTES,
"js-gc-heap",
KIND_OTHER,
nsIMemoryReporter::UNITS_BYTES,
gXPCJSChunkAllocator.GetGCChunkBytesInUse,
"Memory used by the garbage-collected JavaScript heap.")
static PRInt64
GetPerCompartmentSize(PRInt64 (*f)(JSCompartment *c))
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
js::AutoLockGC lock(rt);
PRInt64 n = 0;
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
n += f(*c);
return n;
}
static PRInt64
GetJSStack()
{
@ -1295,246 +1287,384 @@ GetJSStack()
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStack,
"explicit/js/stack",
KIND_MAPPED,
UNITS_BYTES,
nsIMemoryReporter::UNITS_BYTES,
GetJSStack,
"Memory used for the JavaScript stack. This is the committed portion "
"of the stack; any uncommitted portion is not measured because it "
"hardly costs anything.")
static PRInt64
GetCompartmentScriptsSize(JSCompartment *c)
class XPConnectJSCompartmentsMultiReporter : public nsIMemoryMultiReporter
{
PRInt64 n = 0;
for (JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
private:
struct CompartmentStats
{
n += script->totalSize();
}
return n;
}
CompartmentStats(JSContext *cx, JSCompartment *c) {
memset(this, 0, sizeof(*this));
static PRInt64
GetJSScripts()
{
return GetPerCompartmentSize(GetCompartmentScriptsSize);
}
if (c == cx->runtime->atomsCompartment) {
name = NS_LITERAL_CSTRING("atoms");
} else if (c->principals) {
if (c->principals->codebase) {
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.Assign(c->principals->codebase);
char* cur = name.BeginWriting();
char* end = name.EndWriting();
for (; cur < end; ++cur) {
if ('/' == *cur) {
*cur = '\\';
}
}
} else {
name = NS_LITERAL_CSTRING("null-codebase");
}
} else {
name = NS_LITERAL_CSTRING("null-principal");
}
}
struct PRInt64Data {
PRInt64Data() : n(0) { }
PRInt64 n;
};
nsCString name;
PRInt64 gcHeapArenaHeaders;
PRInt64 gcHeapArenaPadding;
PRInt64 gcHeapArenaUnused;
// This function is miscompiled with MSVC 2005 when PGO is on. See bug 664647.
#ifdef _MSC_VER
#pragma optimize("", off)
PRInt64 gcHeapObjects;
PRInt64 gcHeapStrings;
PRInt64 gcHeapShapes;
PRInt64 gcHeapXml;
PRInt64 objectSlots;
PRInt64 stringChars;
PRInt64 scripts;
#ifdef JS_METHODJIT
PRInt64 mjitCode;
PRInt64 mjitData;
#endif
void
GetJSObjectSlotsCallback(JSContext *cx, void *v, size_t traceKind, void *thing)
{
JS_ASSERT(traceKind == JSTRACE_OBJECT);
JSObject *obj = (JSObject *)thing;
if (obj->hasSlotsArray()) {
PRInt64Data *data = (PRInt64Data *) v;
data->n += obj->numSlots() * sizeof(js::Value);
}
}
#ifdef _MSC_VER
#pragma optimize("", on)
#ifdef JS_TRACER
PRInt64 tjitCode;
PRInt64 tjitDataAllocatorsMain;
PRInt64 tjitDataAllocatorsReserve;
#endif
};
static PRInt64
GetJSObjectSlots()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
JSContext *cx = JS_NewContext(rt, 0);
if (!cx) {
NS_ERROR("couldn't create context for memory tracing");
return (PRInt64) -1;
struct IterateData
{
IterateData(JSRuntime *rt)
: compartmentStatsVector()
, currCompartmentStats(NULL)
{
compartmentStatsVector.reserve(rt->compartments.length());
}
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
CompartmentStats *currCompartmentStats;
};
static PRInt64
GetCompartmentScriptsSize(JSCompartment *c)
{
PRInt64 n = 0;
for (JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->totalSize();
}
return n;
}
PRInt64Data data;
js::IterateCells(cx, NULL, js::TraceKindMask(JSTRACE_OBJECT), &data,
*GetJSObjectSlotsCallback);
#ifdef JS_METHODJIT
JS_DestroyContextNoGC(cx);
return data.n;
}
// This function is miscompiled with MSVC 2005 when PGO is on. See bug 664647.
#ifdef _MSC_VER
#pragma optimize("", off)
#endif
void
GetJSStringCharsCallback(JSContext *cx, void *v, size_t traceKind, void *thing)
{
JS_ASSERT(traceKind == JSTRACE_STRING);
JSString *str = (JSString *)thing;
PRInt64Data *data = (PRInt64Data *) v;
data->n += str->charsHeapSize();
}
#ifdef _MSC_VER
#pragma optimize("", on)
#endif
static PRInt64
GetJSStringChars()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
JSContext *cx = JS_NewContext(rt, 0);
if (!cx) {
NS_ERROR("couldn't create context for memory tracing");
return (PRInt64) -1;
static PRInt64
GetCompartmentMjitCodeSize(JSCompartment *c)
{
return c->getMjitCodeSize();
}
PRInt64Data data;
js::IterateCells(cx, NULL, js::TraceKindMask(JSTRACE_STRING), &data,
*GetJSStringCharsCallback);
static PRInt64
GetCompartmentMjitDataSize(JSCompartment *c)
{
PRInt64 n = 0;
for (JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->jitDataSize();
}
return n;
}
JS_DestroyContextNoGC(cx);
#endif // JS_METHODJIT
return data.n;
}
#ifdef JS_TRACER
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSScripts,
"explicit/js/scripts",
KIND_HEAP,
UNITS_BYTES,
GetJSScripts,
"Memory allocated for JSScripts. A JSScript is created for each "
"user-defined function in a script. One is also created for "
"the top-level code in a script. Each JSScript includes byte-code and "
"various other things.")
static PRInt64
GetCompartmentTjitCodeSize(JSCompartment *c)
{
if (c->hasTraceMonitor()) {
size_t total, frag_size, free_size;
c->traceMonitor()->getCodeAllocStats(total, frag_size, free_size);
return total;
}
return 0;
}
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSObjectSlots,
"explicit/js/object-slots",
KIND_HEAP,
UNITS_BYTES,
GetJSObjectSlots,
static PRInt64
GetCompartmentTjitDataAllocatorsMainSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsMainSize()
: 0;
}
static PRInt64
GetCompartmentTjitDataAllocatorsReserveSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsReserveSize()
: 0;
}
#endif // JS_TRACER
static void
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats compartmentStats(cx, compartment);
data->compartmentStatsVector.infallibleAppend(compartmentStats);
CompartmentStats *curr = data->compartmentStatsVector.end() - 1;
data->currCompartmentStats = curr;
// Get the compartment-level numbers.
curr->scripts = GetCompartmentScriptsSize(compartment);
#ifdef JS_METHODJIT
curr->mjitCode = GetCompartmentMjitCodeSize(compartment);
curr->mjitData = GetCompartmentMjitDataSize(compartment);
#endif
#ifdef JS_TRACER
curr->tjitCode = GetCompartmentTjitCodeSize(compartment);
curr->tjitDataAllocatorsMain = GetCompartmentTjitDataAllocatorsMainSize(compartment);
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
#endif
}
static void
ArenaCallback(JSContext *cx, void *vdata, js::gc::Arena *arena,
size_t traceKind, size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
data->currCompartmentStats->gcHeapArenaHeaders +=
sizeof(js::gc::ArenaHeader);
data->currCompartmentStats->gcHeapArenaPadding +=
arena->thingsStartOffset(thingSize) - sizeof(js::gc::ArenaHeader);
// We don't call the callback on unused things. So we compute the
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
// We do this by setting arenaUnused to maxArenaUnused here, and then
// subtracting thingSize for every used cell, in CellCallback().
data->currCompartmentStats->gcHeapArenaUnused += arena->thingsSpan(thingSize);
}
static void
CellCallback(JSContext *cx, void *vdata, void *thing, size_t traceKind,
size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats *curr = data->currCompartmentStats;
if (traceKind == JSTRACE_OBJECT) {
JSObject *obj = static_cast<JSObject *>(thing);
curr->gcHeapObjects += thingSize;
if (obj->hasSlotsArray()) {
curr->objectSlots += obj->numSlots() * sizeof(js::Value);
}
} else if (traceKind == JSTRACE_STRING) {
JSString *str = static_cast<JSString *>(thing);
curr->gcHeapStrings += thingSize;
curr->stringChars += str->charsHeapSize();
} else if (traceKind == JSTRACE_SHAPE) {
curr->gcHeapShapes += thingSize;
} else {
JS_ASSERT(traceKind == JSTRACE_XML);
curr->gcHeapXml += thingSize;
}
// Yes, this is a subtraction: see ArenaCallback() for details.
curr->gcHeapArenaUnused -= thingSize;
}
public:
NS_DECL_ISUPPORTS
XPConnectJSCompartmentsMultiReporter()
{
}
nsCString mkPath(const nsACString &compartmentName,
const char* reporterName)
{
nsCString path(NS_LITERAL_CSTRING("explicit/js/compartment("));
path += compartmentName;
path += NS_LITERAL_CSTRING(")/");
path += nsDependentCString(reporterName);
return path;
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
IterateData data(rt);
// In the first step we get all the stats and stash them in a local
// data structure. In the second step we pass all the stashed stats to
// the callback. Separating these steps is important because the
// callback may be a JS function, and executing JS while getting these
// stats seems like a bad idea.
{
JSContext *cx = JS_NewContext(rt, 0);
if (!cx) {
NS_ERROR("couldn't create context for memory tracing");
return NS_ERROR_FAILURE;
}
JS_BeginRequest(cx);
js::IterateCompartmentsArenasCells(cx, &data, CompartmentCallback, ArenaCallback,
CellCallback);
JS_EndRequest(cx);
JS_DestroyContextNoGC(cx);
}
NS_NAMED_LITERAL_CSTRING(p, "");
PRInt64 gcHeapChunkTotal = gXPCJSChunkAllocator.GetGCChunkBytesInUse();
// This is initialized to gcHeapChunkUnused, and then we subtract used
// space from it each time around the loop.
PRInt64 gcHeapChunkUnused = gcHeapChunkTotal;
#define DO(path, kind, amount, desc) \
callback->Callback(p, path, kind, nsIMemoryReporter::UNITS_BYTES, \
amount, NS_LITERAL_CSTRING(desc), closure);
// This is the second step (see above).
for (CompartmentStats *stats = data.compartmentStatsVector.begin();
stats != data.compartmentStatsVector.end();
++stats)
{
nsCString &name = stats->name;
gcHeapChunkUnused -=
stats->gcHeapArenaHeaders + stats->gcHeapArenaPadding +
stats->gcHeapArenaUnused +
stats->gcHeapObjects + stats->gcHeapStrings +
stats->gcHeapShapes + stats->gcHeapXml;
DO(mkPath(name, "gc-heap/arena-headers"),
JS_GC_HEAP_KIND, stats->gcHeapArenaHeaders,
"Memory on the garbage-collected JavaScript heap, within arenas, that is "
"used to hold internal book-keeping information.");
DO(mkPath(name, "gc-heap/arena-padding"),
JS_GC_HEAP_KIND, stats->gcHeapArenaPadding,
"Memory on the garbage-collected JavaScript heap, within arenas, that is "
"unused and present only so that other data is aligned.");
DO(mkPath(name, "gc-heap/arena-unused"),
JS_GC_HEAP_KIND, stats->gcHeapArenaUnused,
"Memory on the garbage-collected JavaScript heap, within arenas, that "
"could be holding useful data but currently isn't.");
DO(mkPath(name, "gc-heap/objects"),
JS_GC_HEAP_KIND, stats->gcHeapObjects,
"Memory on the garbage-collected JavaScript heap that holds objects.");
DO(mkPath(name, "gc-heap/strings"),
JS_GC_HEAP_KIND, stats->gcHeapStrings,
"Memory on the garbage-collected JavaScript heap that holds string "
"headers.");
DO(mkPath(name, "gc-heap/shapes"),
JS_GC_HEAP_KIND, stats->gcHeapShapes,
"Memory on the garbage-collected JavaScript heap that holds shapes. "
"A shape is an internal data structure that makes property accesses "
"fast.");
DO(mkPath(name, "gc-heap/xml"),
JS_GC_HEAP_KIND, stats->gcHeapXml,
"Memory on the garbage-collected JavaScript heap that holds E4X XML "
"objects.");
DO(mkPath(name, "object-slots"),
nsIMemoryReporter::KIND_HEAP, stats->objectSlots,
"Memory allocated for non-fixed object slot arrays, which are used "
"to represent object properties. Some objects also contain a fixed "
"number of slots which are stored on the JavaScript heap; those slots "
"are not counted here.")
"are not counted here, but in 'gc-heap/objects'.");
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStringChars,
"explicit/js/string-chars",
KIND_HEAP,
UNITS_BYTES,
GetJSStringChars,
DO(mkPath(name, "string-chars"),
nsIMemoryReporter::KIND_HEAP, stats->stringChars,
"Memory allocated to hold string characters. Not all of this allocated "
"memory is necessarily used to hold characters. Each string also "
"includes a header which is stored on the JavaScript heap; that header "
"is not counted here.")
"is not counted here, but in 'gc-heap/strings'.");
DO(mkPath(name, "scripts"),
nsIMemoryReporter::KIND_HEAP, stats->scripts,
"Memory allocated for JSScripts. A JSScript is created for each "
"user-defined function in a script. One is also created for "
"the top-level code in a script. Each JSScript includes byte-code and "
"various other things.");
#ifdef JS_METHODJIT
DO(mkPath(name, "mjit-code"),
nsIMemoryReporter::KIND_MAPPED, stats->mjitCode,
"Memory used by the method JIT to hold generated code.");
static PRInt64
GetCompartmentMjitCodeSize(JSCompartment *c)
{
return c->getMjitCodeSize();
}
static PRInt64
GetJSMjitCode()
{
return GetPerCompartmentSize(GetCompartmentMjitCodeSize);
}
static PRInt64
GetJSMJitData()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
return rt->mjitDataSize;
}
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSMjitCode,
"explicit/js/mjit-code",
KIND_MAPPED,
UNITS_BYTES,
GetJSMjitCode,
"Memory used by the method JIT to hold generated code.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSMjitData,
"explicit/js/mjit-data",
KIND_HEAP,
UNITS_BYTES,
GetJSMJitData,
DO(mkPath(name, "mjit-data"),
nsIMemoryReporter::KIND_HEAP, stats->mjitData,
"Memory used by the method JIT for the following data: "
"JITScripts, native maps, and inline cache structs.")
#endif // JS_METHODJIT
"JITScripts, native maps, and inline cache structs.");
#endif
#ifdef JS_TRACER
DO(mkPath(name, "tjit-code"),
nsIMemoryReporter::KIND_MAPPED, stats->tjitCode,
"Memory used by the trace JIT to hold generated code.");
static PRInt64
GetCompartmentTjitCode(JSCompartment *c)
{
if (c->hasTraceMonitor()) {
size_t total, frag_size, free_size;
c->traceMonitor()->getCodeAllocStats(total, frag_size, free_size);
return total;
}
return 0;
}
DO(mkPath(name, "tjit-data/allocators-main"),
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsMain,
"Memory used by the trace JIT's VMAllocators.");
static PRInt64
GetCompartmentTjitDataAllocatorsMain(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsMainSize()
: 0;
}
static PRInt64
GetCompartmentTjitDataAllocatorsReserve(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsReserveSize()
: 0;
}
static PRInt64
GetJSTjitCode()
{
return GetPerCompartmentSize(GetCompartmentTjitCode);
}
static PRInt64
GetJSTjitDataAllocatorsMain()
{
return GetPerCompartmentSize(GetCompartmentTjitDataAllocatorsMain);
}
static PRInt64
GetJSTjitDataAllocatorsReserve()
{
return GetPerCompartmentSize(GetCompartmentTjitDataAllocatorsReserve);
}
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitCode,
"explicit/js/tjit-code",
KIND_MAPPED,
UNITS_BYTES,
GetJSTjitCode,
"Memory used by the trace JIT to hold generated code.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitDataAllocatorsMain,
"explicit/js/tjit-data/allocators-main",
KIND_HEAP,
UNITS_BYTES,
GetJSTjitDataAllocatorsMain,
"Memory used by the trace JIT's VMAllocators.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitDataAllocatorsReserve,
"explicit/js/tjit-data/allocators-reserve",
KIND_HEAP,
UNITS_BYTES,
GetJSTjitDataAllocatorsReserve,
DO(mkPath(name, "tjit-data/allocators-reserve"),
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsReserve,
"Memory used by the trace JIT and held in reserve for VMAllocators "
"in case of OOM.")
"in case of OOM.");
#endif
}
#endif // JS_TRACER
JS_ASSERT(gcHeapChunkTotal % js::GC_CHUNK_SIZE == 0);
size_t numChunks = gcHeapChunkTotal / js::GC_CHUNK_SIZE;
PRInt64 perChunkAdmin =
sizeof(js::gc::Chunk) - (sizeof(js::gc::Arena) * js::gc::ArenasPerChunk);
PRInt64 gcHeapChunkAdmin = numChunks * perChunkAdmin;
gcHeapChunkUnused -= gcHeapChunkAdmin;
DO(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-unused"),
JS_GC_HEAP_KIND, gcHeapChunkUnused,
"Memory on the garbage-collected JavaScript heap, within chunks, that "
"could be holding useful data but currently isn't.");
DO(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-admin"),
JS_GC_HEAP_KIND, gcHeapChunkAdmin,
"Memory on the garbage-collected JavaScript heap, within chunks, that is "
"used to hold internal book-keeping information.");
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(
XPConnectJSCompartmentsMultiReporter
, nsIMemoryMultiReporter
)
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
: mXPConnect(aXPConnect),
@ -1603,18 +1733,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSStack));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSScripts));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSObjectSlots));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSStringChars));
#ifdef JS_METHODJIT
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSMjitCode));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSMjitData));
#endif
#ifdef JS_TRACER
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitCode));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitDataAllocatorsMain));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitDataAllocatorsReserve));
#endif
NS_RegisterMemoryMultiReporter(new XPConnectJSCompartmentsMultiReporter);
}
if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,

View File

@ -557,11 +557,6 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
#define NS_STYLE_LIST_STYLE_KATAKANA 16
#define NS_STYLE_LIST_STYLE_HIRAGANA_IROHA 17
#define NS_STYLE_LIST_STYLE_KATAKANA_IROHA 18
#define NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN 19
#define NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN 20
#define NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA 21
#define NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA 22
#define NS_STYLE_LIST_STYLE_OLD_DECIMAL 23
#define NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM 24
#define NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH 25
#define NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL 26

View File

@ -88,6 +88,60 @@ _TEST_FILES = \
test_bug435293-scale.html \
test_bug435293-interaction.html \
test_bug435293-skew.html \
test_reftests_with_caret.html \
bug106855-1.html \
bug106855-2.html \
bug106855-1-ref.html \
bug240933-1.html \
bug240933-2.html \
bug240933-1-ref.html \
bug389321-1.html \
bug389321-1-ref.html \
bug389321-2.html \
bug389321-2-ref.html \
bug389321-3.html \
bug389321-3-ref.html \
bug482484.html \
bug482484-ref.html \
bug512295-1.html \
bug512295-1-ref.html \
bug512295-2.html \
bug512295-2-ref.html \
bug585922.html \
bug585922-ref.html \
bug597519-1.html \
bug597519-1-ref.html \
bug602141-1.html \
bug602141-1-ref.html \
bug602141-2.html \
bug602141-2-ref.html \
bug602141-3.html \
bug602141-3-ref.html \
bug602141-4.html \
bug602141-4-ref.html \
bug612271-1.html \
bug612271-2.html \
bug612271-3.html \
bug612271-ref.html \
bug613433-1.html \
bug613433-2.html \
bug613433-3.html \
bug613433-ref.html \
bug613807-1.html \
bug613807-1-ref.html \
bug632215-1.html \
bug632215-2.html \
bug632215-ref.html \
bug633044-1.html \
bug633044-1-ref.html \
bug634406-1.html \
bug634406-1-ref.html \
bug644428-1.html \
bug644428-1-ref.html \
bug646382-1.html \
bug646382-1-ref.html \
bug646382-2.html \
bug646382-2-ref.html \
test_bug514127.html \
test_bug518777.html \
test_bug548545.xhtml \

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
x<br>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
x<br>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
x<br>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<textarea id="t" rows="4"></textarea>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<textarea id="t" rows="4"></textarea>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<span contenteditable id="t" style="border: 1px dashed green; min-height: 2px; padding-right: 20px;"> </span></body>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<span contenteditable id="t" style="border: 1px dashed green; min-height: 2px; padding-right: 20px;"> </span></body>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<div contentEditable="true" id="div"><p id="p">BC</p></div>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<div contenteditable="true">

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<div contenteditable="true">

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
x

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
x

View File

@ -1,12 +1,15 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body onload="doTest()">
<input type=text>
<script>
function doTest() {
netscape.security.PrivilegeManager.enablePrivilege(
"UniversalXPConnect");
var d = document.querySelector("input");
d.value = "b";
d.focus();

View File

@ -1,12 +1,14 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body onload="doTest()">
<input type=text>
<script>
function doTest() {
netscape.security.PrivilegeManager.enablePrivilege(
"UniversalXPConnect");
function enableCaret(aEnable) {
var selCon = editor.selectionController;
selCon.setCaretEnabled(aEnable);
@ -20,6 +22,8 @@
var t = editor.rootElement.firstChild;
sel.collapse(t, 1); // put the caret at the end of the div
setTimeout(function() {
netscape.security.PrivilegeManager.enablePrivilege(
"UniversalXPConnect");
enableCaret(false);enableCaret(true);// force a caret display
enableCaret(false); // hide the caret
t.replaceData(0, 1, "b"); // replace the text node data

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<textarea maxlength="3"></textarea>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<span contenteditable="true">navigable__</span><span id="x" contenteditable="true">navigable|unnavigable</span><br />

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<span id="x" contenteditable="true">navigable__|</span><br />

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
noteditable<span id="x" contenteditable="true">navigable|unnavigable</span><br />

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<span>not editable</span><span id="x" contenteditable="true">navigable|unnavigable</span>

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML><html><head>
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<textarea id="target" style="height: 100px"

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