mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Merge m-c to b-s
This commit is contained in:
commit
26d60b6f50
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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 -->
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
104
accessible/tests/mochitest/tree/test_aria_presentation.html
Normal file
104
accessible/tests/mochitest/tree/test_aria_presentation.html
Normal 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>
|
@ -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"),
|
||||
|
@ -15,6 +15,7 @@ function test() {
|
||||
if (topic != "page-info-dialog-loaded")
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
handlePageInfo();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1534,6 +1534,8 @@ public:
|
||||
#undef DEPRECATED_OPERATION
|
||||
void WarnOnceAbout(DeprecatedOperations aOperation);
|
||||
|
||||
PRInt64 SizeOf() const;
|
||||
|
||||
private:
|
||||
PRUint32 mWarnedAbout;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);"));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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>
|
||||
|
@ -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');
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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"/>
|
||||
|
@ -112,6 +112,7 @@ CPPSRCS = \
|
||||
nsStructuredCloneContainer.cpp \
|
||||
nsDOMNavigationTiming.cpp \
|
||||
nsPerformance.cpp \
|
||||
nsDOMMemoryReporter.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
110
dom/base/nsDOMMemoryReporter.cpp
Normal file
110
dom/base/nsDOMMemoryReporter.cpp
Normal 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;
|
||||
}
|
||||
|
63
dom/base/nsDOMMemoryReporter.h
Normal file
63
dom/base/nsDOMMemoryReporter.h
Normal 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__
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
void SetIsBackground(PRBool aIsBackground)
|
||||
virtual void SetIsBackground(PRBool aIsBackground)
|
||||
{
|
||||
mIsBackground = aIsBackground;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 \
|
||||
|
8
editor/libeditor/html/tests/file_bug549262.html
Normal file
8
editor/libeditor/html/tests/file_bug549262.html
Normal 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>
|
38
editor/libeditor/html/tests/test_bug439808.html
Normal file
38
editor/libeditor/html/tests/test_bug439808.html
Normal 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>
|
74
editor/libeditor/html/tests/test_bug549262.html
Normal file
74
editor/libeditor/html/tests/test_bug549262.html
Normal 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>
|
22
gfx/2d/2D.h
22
gfx/2d/2D.h
@ -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;
|
||||
};
|
||||
|
@ -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.";
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Point.h"
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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">
|
@ -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">
|
@ -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
|
@ -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
|
@ -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();
|
@ -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
|
@ -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>
|
@ -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 />
|
@ -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 />
|
@ -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 />
|
@ -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>
|
@ -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
Loading…
Reference in New Issue
Block a user