Bug 776536 part 4. Turn on WebIDL bindings for NodeIterator and TreeWalker. r=peterv

The behavior here is a bit weird because Document is still not a
WebIDL object, so calling createNodeIterator or createTreeWalker via
an Xray will call the XPCOM versions of those methods.  That means
that I can't just disable XPCOM-based wrapping for TreeWalker and
NodeIterator altogether, unfortunately, which means a web page could
try stashing a TreeWalker in something like userdata and then getting
it back and end up wrapping it as an XPCOM object the second time.

I could "fix" that by adding a wrapper cache and whatnot, I guess, if
desired...  But the problem will go away once we convert Document in
any case.
This commit is contained in:
Boris Zbarsky 2013-02-28 12:56:42 -05:00
parent 36e1af6705
commit 24d39ed923
14 changed files with 51 additions and 94 deletions

View File

@ -96,7 +96,9 @@ class GlobalObject;
class HTMLBodyElement;
class Link;
class NodeFilter;
class NodeIterator;
class ProcessingInstruction;
class TreeWalker;
class UndoManager;
template<typename> class Sequence;
@ -1939,18 +1941,18 @@ public:
already_AddRefed<nsIDOMEvent> CreateEvent(const nsAString& aEventType,
mozilla::ErrorResult& rv) const;
already_AddRefed<nsRange> CreateRange(mozilla::ErrorResult& rv);
already_AddRefed<nsIDOMNodeIterator>
already_AddRefed<mozilla::dom::NodeIterator>
CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
mozilla::dom::NodeFilter* aFilter,
mozilla::ErrorResult& rv) const;
already_AddRefed<nsIDOMNodeIterator>
already_AddRefed<mozilla::dom::NodeIterator>
CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
const mozilla::dom::NodeFilterHolder& aFilter,
mozilla::ErrorResult& rv) const;
already_AddRefed<nsIDOMTreeWalker>
already_AddRefed<mozilla::dom::TreeWalker>
CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
mozilla::dom::NodeFilter* aFilter, mozilla::ErrorResult& rv) const;
already_AddRefed<nsIDOMTreeWalker>
already_AddRefed<mozilla::dom::TreeWalker>
CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
const mozilla::dom::NodeFilterHolder& aFilter,
mozilla::ErrorResult& rv) const;

View File

@ -18,6 +18,7 @@
#include "nsDOMClassInfoID.h"
#include "nsContentUtils.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/NodeIteratorBinding.h"
DOMCI_DATA(NodeIterator, mozilla::dom::NodeIterator)
@ -300,5 +301,11 @@ void NodeIterator::ContentRemoved(nsIDocument *aDocument,
mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
}
JSObject*
NodeIterator::WrapObject(JSContext *cx, JSObject *scope)
{
return NodeIteratorBinding::Wrap(cx, scope, this);
}
} // namespace dom
} // namespace mozilla

View File

@ -22,9 +22,9 @@ class nsIDOMNode;
namespace mozilla {
namespace dom {
class NodeIterator : public nsIDOMNodeIterator,
public nsTraversal,
public nsStubMutationObserver
class NodeIterator MOZ_FINAL : public nsIDOMNodeIterator,
public nsTraversal,
public nsStubMutationObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -70,6 +70,8 @@ public:
}
// The XPCOM Detach() is fine for our purposes
JSObject* WrapObject(JSContext *cx, JSObject *scope);
private:
struct NodePointer {
NodePointer() : mNode(nullptr) {}

View File

@ -15,6 +15,7 @@
#include "nsINode.h"
#include "nsDOMClassInfoID.h"
#include "nsContentUtils.h"
#include "mozilla/dom/TreeWalkerBinding.h"
DOMCI_DATA(TreeWalker, mozilla::dom::TreeWalker)
@ -449,5 +450,11 @@ TreeWalker::NextSiblingInternal(bool aReversed, ErrorResult& aResult)
}
}
JSObject*
TreeWalker::WrapObject(JSContext *cx, JSObject *scope)
{
return TreeWalkerBinding::Wrap(cx, scope, this);
}
} // namespace dom
} // namespace mozilla

View File

@ -23,7 +23,7 @@ class nsIDOMNode;
namespace mozilla {
namespace dom {
class TreeWalker : public nsIDOMTreeWalker, public nsTraversal
class TreeWalker MOZ_FINAL : public nsIDOMTreeWalker, public nsTraversal
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -64,6 +64,8 @@ public:
already_AddRefed<nsINode> PreviousNode(ErrorResult& aResult);
already_AddRefed<nsINode> NextNode(ErrorResult& aResult);
JSObject* WrapObject(JSContext *cx, JSObject *scope);
private:
nsCOMPtr<nsINode> mCurrentNode;

View File

@ -4746,7 +4746,7 @@ nsDocument::CreateProcessingInstruction(const nsAString& aTarget,
already_AddRefed<ProcessingInstruction>
nsIDocument::CreateProcessingInstruction(const nsAString& aTarget,
const nsAString& aData,
mozilla::ErrorResult& rv) const
ErrorResult& rv) const
{
nsresult res = nsContentUtils::CheckQName(aTarget, false);
if (NS_FAILED(res)) {
@ -4823,7 +4823,7 @@ nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI,
already_AddRefed<nsIDOMAttr>
nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aQualifiedName,
mozilla::ErrorResult& rv)
ErrorResult& rv)
{
WarnOnceAbout(eCreateAttributeNS);
@ -5361,23 +5361,19 @@ nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
return rv.ErrorCode();
}
already_AddRefed<nsIDOMNodeIterator>
already_AddRefed<NodeIterator>
nsIDocument::CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
NodeFilter* aFilter,
mozilla::ErrorResult& rv) const
ErrorResult& rv) const
{
NodeFilterHolder holder(aFilter);
// We don't really know how to handle WebIDL callbacks yet, in
// nsTraversal, so just go ahead and convert to an XPCOM callback.
nsCOMPtr<nsIDOMNodeFilter> filter = holder.ToXPCOMCallback();
NodeFilterHolder holder2(filter);
return CreateNodeIterator(aRoot, aWhatToShow, holder2, rv);
return CreateNodeIterator(aRoot, aWhatToShow, holder, rv);
}
already_AddRefed<nsIDOMNodeIterator>
already_AddRefed<NodeIterator>
nsIDocument::CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
const NodeFilterHolder& aFilter,
mozilla::ErrorResult& rv) const
ErrorResult& rv) const
{
nsINode* root = &aRoot;
nsresult res = nsContentUtils::CheckSameOrigin(this, root);
@ -5414,20 +5410,16 @@ nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
return rv.ErrorCode();
}
already_AddRefed<nsIDOMTreeWalker>
already_AddRefed<TreeWalker>
nsIDocument::CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
NodeFilter* aFilter,
ErrorResult& rv) const
{
NodeFilterHolder holder(aFilter);
// We don't really know how to handle WebIDL callbacks yet, in
// nsTraversal, so just go ahead and convert to an XPCOM callback.
nsCOMPtr<nsIDOMNodeFilter> filter = holder.ToXPCOMCallback();
NodeFilterHolder holder2(filter);
return CreateTreeWalker(aRoot, aWhatToShow, holder2, rv);
return CreateTreeWalker(aRoot, aWhatToShow, holder, rv);
}
already_AddRefed<nsIDOMTreeWalker>
already_AddRefed<TreeWalker>
nsIDocument::CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
const NodeFilterHolder& aFilter,
ErrorResult& rv) const

View File

@ -61,7 +61,8 @@ nsTraversal::TestNode(nsINode* aNode, mozilla::ErrorResult& aResult)
if (mFilter.HasWebIDLCallback()) {
AutoRestore<bool> inAcceptNode(mInAcceptNode);
mInAcceptNode = true;
return mFilter.GetWebIDLCallback()->AcceptNode(*aNode, aResult);
return mFilter.GetWebIDLCallback()->
AcceptNode(*aNode, aResult, CallbackObject::eRethrowExceptions);
}
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);

View File

@ -534,9 +534,9 @@ DOMInterfaces = {
'attributes' ]
},
'NodeFilter': {
'nativeType': 'nsIDOMNodeFilter',
'headerFile': 'nsIDOMNodeFilter.h',
'NodeIterator': {
'wrapperCache': False,
'resultNotAddRefed': [ 'root', 'referenceNode' ],
},
'NodeList': {
@ -848,6 +848,11 @@ DOMInterfaces = {
'implicitJSContext': [ 'encode' ],
}],
'TreeWalker': {
'wrapperCache': False,
'resultNotAddRefed': [ 'root', 'currentNode' ],
},
'URL' : [{
'concrete': False,
},
@ -1212,7 +1217,6 @@ addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSou
addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
addExternalIface('NamedNodeMap')
addExternalIface('NodeIterator')
addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
addExternalIface('nsISupports', nativeType='nsISupports')
addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
@ -1230,7 +1234,6 @@ addExternalIface('SVGAnimatedString')
addExternalIface('SVGLength')
addExternalIface('SVGNumber')
addExternalIface('TextMetrics', headerFile='nsIDOMCanvasRenderingContext2D.h')
addExternalIface('TreeWalker')
addExternalIface('Touch', headerFile='nsIDOMTouchEvent.h')
addExternalIface('TouchList', headerFile='nsIDOMTouchEvent.h')
addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',

View File

@ -131,23 +131,6 @@
"Range interface: calling isPointInRange(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
"Range interface: calling comparePoint(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
"Range interface: calling intersectsNode(Node) on detachedRange with too few arguments must throw TypeError": true,
"NodeIterator interface: existence and properties of interface object": true,
"NodeIterator interface: existence and properties of interface prototype object": true,
"NodeIterator interface: existence and properties of interface prototype object's \"constructor\" property": true,
"NodeIterator interface: attribute root": true,
"NodeIterator interface: attribute referenceNode": true,
"NodeIterator interface: attribute pointerBeforeReferenceNode": true,
"NodeIterator interface: attribute whatToShow": true,
"NodeIterator interface: attribute filter": true,
"Stringification of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null)": "debug",
"TreeWalker interface: existence and properties of interface object": true,
"TreeWalker interface: existence and properties of interface prototype object": true,
"TreeWalker interface: existence and properties of interface prototype object's \"constructor\" property": true,
"TreeWalker interface: attribute root": true,
"TreeWalker interface: attribute whatToShow": true,
"TreeWalker interface: attribute filter": true,
"TreeWalker interface: attribute currentNode": true,
"Stringification of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null)": "debug",
"NodeFilter interface: existence and properties of interface object": true,
"NodeFilter interface: existence and properties of interface prototype object": true,
"NodeFilter interface: existence and properties of interface prototype object's \"constructor\" property": true,

View File

@ -17,12 +17,10 @@
interface Attr;
interface Comment;
interface NodeIterator;
interface Range;
interface StyleSheetList;
interface Touch;
interface TouchList;
interface TreeWalker;
interface WindowProxy;
interface nsISupports;

View File

@ -28,4 +28,4 @@ interface NodeIterator {
Node? previousNode();
void detach();
;}
};

View File

@ -121,6 +121,7 @@ webidl_files = \
MutationObserver.webidl \
Node.webidl \
NodeFilter.webidl \
NodeIterator.webidl \
NodeList.webidl \
PaintRequest.webidl \
PaintRequestList.webidl \
@ -211,6 +212,7 @@ webidl_files = \
Text.webidl \
TextDecoder.webidl \
TextEncoder.webidl \
TreeWalker.webidl \
URL.webidl \
ValidityState.webidl \
WebSocket.webidl \

View File

@ -37,7 +37,6 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \
test_bug478438.html \
test_bug500691.html \
bug500931_helper.html \
test_bug502959.html \
test_bug503926.html \
test_bug504877.html \
bug504877_helper.html \

View File

@ -1,41 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=502959
-->
<head>
<title>Test for Bug 502959</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=502959">Mozilla Bug 502959</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 502959 **/
// Whatever you do don't use the word "wrapped" in this function.
function foo() {
ok(true, "Able to call the function");
}
var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, foo);
var doublewrapped = iter.filter;
ok(doublewrapped.toString().indexOf("wrapped") > 0, "got a double-wrapped object back");
(function () {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Components.utils.forceGC();
})();
doublewrapped.acceptNode(document);
</script>
</pre>
</body>
</html>