Bug 842561. Assert that our inheritance chain is correct for WebIDL objects. r=peterv

We could drop the descriptor for Text if we changed nsIDocument::CreateTextNode
to return an already_AddRefed<Text>, but then we'd need more casting in
nsDocument.cpp for the XPCOM CreateTextNode.  Not sure which way is better,
really.
This commit is contained in:
Boris Zbarsky 2013-02-22 09:56:29 -05:00
parent 12d1591d42
commit d917523d97
8 changed files with 88 additions and 30 deletions

View File

@ -51,6 +51,7 @@ EXPORTS_mozilla/dom = \
DOMImplementation.h \
EventSource.h \
Link.h \
Text.h \
$(NULL)
CPPSRCS = \
@ -120,6 +121,7 @@ CPPSRCS = \
nsStyledElement.cpp \
nsStyleLinkElement.cpp \
nsSyncLoadService.cpp \
Text.cpp \
nsTextFragment.cpp \
nsTextNode.cpp \
nsTraversal.cpp \

23
content/base/src/Text.cpp Normal file
View File

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Text.h"
namespace mozilla {
namespace dom {
already_AddRefed<Text>
Text::SplitText(uint32_t aOffset, ErrorResult& rv)
{
nsCOMPtr<nsIContent> newChild;
rv = SplitData(aOffset, getter_AddRefs(newChild));
if (rv.Failed()) {
return nullptr;
}
return static_cast<Text*>(newChild.forget().get());
}
} // namespace dom
} // namespace mozilla

35
content/base/src/Text.h Normal file
View File

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_Text_h
#define mozilla_dom_Text_h
#include "nsGenericDOMDataNode.h"
#include "mozilla/ErrorResult.h"
namespace mozilla {
namespace dom {
class Text : public nsGenericDOMDataNode
{
public:
Text(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
{}
using nsGenericDOMDataNode::GetWholeText;
// WebIDL API
already_AddRefed<Text> SplitText(uint32_t aOffset, ErrorResult& rv);
void GetWholeText(nsAString& aWholeText, ErrorResult& rv)
{
rv = GetWholeText(aWholeText);
}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_Text_h

View File

@ -185,17 +185,6 @@ void nsTextNode::UnbindFromTree(bool aDeep, bool aNullParent)
nsGenericDOMDataNode::UnbindFromTree(aDeep, aNullParent);
}
already_AddRefed<nsTextNode>
nsTextNode::SplitText(uint32_t aOffset, ErrorResult& rv)
{
nsCOMPtr<nsIContent> newChild;
rv = SplitData(aOffset, getter_AddRefs(newChild));
if (rv.Failed()) {
return nullptr;
}
return static_cast<nsTextNode*>(newChild.forget().get());
}
#ifdef DEBUG
void
nsTextNode::List(FILE* out, int32_t aIndent) const

View File

@ -10,19 +10,19 @@
* Implementation of DOM Core's nsIDOMText node.
*/
#include "nsGenericDOMDataNode.h"
#include "mozilla/dom/Text.h"
#include "nsIDOMText.h"
#include "nsDebug.h"
/**
* Class used to implement DOM text nodes
*/
class nsTextNode : public nsGenericDOMDataNode,
class nsTextNode : public mozilla::dom::Text,
public nsIDOMText
{
public:
nsTextNode(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
: mozilla::dom::Text(aNodeInfo)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
"Bad NodeType in aNodeInfo");
@ -62,14 +62,6 @@ public:
virtual nsIDOMNode* AsDOMNode() { return this; }
// WebIDL API
already_AddRefed<nsTextNode> SplitText(uint32_t aOffset,
mozilla::ErrorResult& rv);
void GetWholeText(nsAString& aWholeText, mozilla::ErrorResult& rv)
{
rv = GetWholeText(aWholeText);
}
#ifdef DEBUG
virtual void List(FILE* out, int32_t aIndent) const;
virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const;

View File

@ -7,17 +7,17 @@
#define mozilla_dom_CDATASection_h
#include "nsIDOMCDATASection.h"
#include "nsGenericDOMDataNode.h"
#include "mozilla/dom/Text.h"
namespace mozilla {
namespace dom {
class CDATASection : public nsGenericDOMDataNode,
class CDATASection : public Text,
public nsIDOMCDATASection
{
public:
CDATASection(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
: Text(aNodeInfo)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE,
"Bad NodeType in aNodeInfo");

View File

@ -825,7 +825,9 @@ DOMInterfaces = {
},
'Text': {
'nativeType': 'nsTextNode',
# Total hack to allow binding code to realize that nsTextNode can
# in fact be cast to Text.
'headerFile': 'nsTextNode.h',
},
'TextDecoder': [

View File

@ -1819,6 +1819,18 @@ def InitUnforgeableProperties(descriptor, properties):
"// finalizer trying to drop its ownership of the C++ object.\n"),
post="\n")).define() if len(unforgeables) > 0 else ""
def AssertInheritanceChain(descriptor):
asserts = ""
iface = descriptor.interface
while iface:
desc = descriptor.getDescriptor(iface.identifier.name)
asserts += (
" MOZ_ASSERT(static_cast<%s*>(aObject) == \n"
" reinterpret_cast<%s*>(aObject));\n" %
(desc.nativeType, desc.nativeType))
iface = iface.parent
return asserts
class CGWrapWithCacheMethod(CGAbstractMethod):
"""
Create a wrapper JSObject for a given native that implements nsWrapperCache.
@ -1839,7 +1851,8 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
return """ *aTriedToWrap = true;
return aObject->GetJSObject();"""
return """ *aTriedToWrap = true;
return """%s
*aTriedToWrap = true;
JSObject* parent = WrapNativeParent(aCx, aScope, aObject->GetParentObject());
if (!parent) {
@ -1868,7 +1881,8 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
%s
aCache->SetWrapper(obj);
return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aCache"),
return obj;""" % (AssertInheritanceChain(self.descriptor),
CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aCache"),
CreateBindingJSObject(self.descriptor, "parent"),
InitUnforgeableProperties(self.descriptor, self.properties))
@ -1899,7 +1913,7 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
self.properties = properties
def definition_body(self):
return """
return """%s
JSObject* global = JS_GetGlobalForObject(aCx, aScope);
JSObject* proto = GetProtoObject(aCx, global);
if (!proto) {
@ -1908,7 +1922,8 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
%s
%s
return obj;""" % (CreateBindingJSObject(self.descriptor, "global"),
return obj;""" % (AssertInheritanceChain(self.descriptor),
CreateBindingJSObject(self.descriptor, "global"),
InitUnforgeableProperties(self.descriptor, self.properties))
builtinNames = {