CTTE: Add more node conversion helpers
https://bugs.webkit.org/show_bug.cgi?id=122737

Reviewed by Darin Adler.

- Factor NODE_TYPE_CASTS into TYPE_CASTS_BASE(ToClassName, FromClassName)
  to allow for DOCUMENT_TYPE_CASTS.
- Replace more static_casts<>.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@157405 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 3d841a2..59057de 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,14 @@
+2013-10-13  Sam Weinig  <sam@webkit.org>
+
+        CTTE: Add more node conversion helpers
+        https://bugs.webkit.org/show_bug.cgi?id=122737
+
+        Reviewed by Darin Adler.
+
+        - Factor NODE_TYPE_CASTS into TYPE_CASTS_BASE(ToClassName, FromClassName)
+          to allow for DOCUMENT_TYPE_CASTS.
+        - Replace more static_casts<>.
+
 2013-10-14  Zan Dobersek  <zdobersek@igalia.com>
 
         Reintroduce PassRefPtr<Event> copy in ScopedEventQueue::dispatchEvent
diff --git a/Source/WebCore/dom/Attr.h b/Source/WebCore/dom/Attr.h
index 269d0b0..b8f4228 100644
--- a/Source/WebCore/dom/Attr.h
+++ b/Source/WebCore/dom/Attr.h
@@ -102,6 +102,11 @@
     bool m_specified : 1;
 };
 
+inline bool isAttr(const Node& node) { return node.isAttributeNode(); }
+void isAttr(const Attr&); // Catch unnecessary runtime check of type known at compile time.
+
+NODE_TYPE_CASTS(Attr)
+
 } // namespace WebCore
 
 #endif // Attr_h
diff --git a/Source/WebCore/dom/CDATASection.h b/Source/WebCore/dom/CDATASection.h
index 213b91d..b4c762b4 100644
--- a/Source/WebCore/dom/CDATASection.h
+++ b/Source/WebCore/dom/CDATASection.h
@@ -41,10 +41,9 @@
     virtual PassRefPtr<Text> virtualCreate(const String&) OVERRIDE;
 };
 
-inline bool isCDATASection(const Node& node)
-{
-    return node.nodeType() == Node::CDATA_SECTION_NODE;
-}
+inline bool isCDATASection(const Node& node) { return node.nodeType() == Node::CDATA_SECTION_NODE; }
+void isCDATASection(const CDATASection&); // Catch unnecessary runtime check of type known at compile time.
+void isCDATASection(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
 
 NODE_TYPE_CASTS(CDATASection)
 
diff --git a/Source/WebCore/dom/CharacterData.h b/Source/WebCore/dom/CharacterData.h
index 76723da..db18d40 100644
--- a/Source/WebCore/dom/CharacterData.h
+++ b/Source/WebCore/dom/CharacterData.h
@@ -74,6 +74,12 @@
     String m_data;
 };
 
+inline bool isCharacterData(const Node& node) { return node.isCharacterDataNode(); }
+void isCharacterData(const CharacterData&); // Catch unnecessary runtime check of type known at compile time.
+void isCharacterData(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
+
+NODE_TYPE_CASTS(CharacterData)
+
 } // namespace WebCore
 
 #endif // CharacterData_h
diff --git a/Source/WebCore/dom/Comment.h b/Source/WebCore/dom/Comment.h
index 6e2f8ef..4f63b7f 100644
--- a/Source/WebCore/dom/Comment.h
+++ b/Source/WebCore/dom/Comment.h
@@ -40,10 +40,9 @@
     virtual bool childTypeAllowed(NodeType) const;
 };
 
-inline bool isComment(const Node& node)
-{
-    return node.nodeType() == Node::COMMENT_NODE;
-}
+inline bool isComment(const Node& node) { return node.nodeType() == Node::COMMENT_NODE; }
+void isComment(const Comment&); // Catch unnecessary runtime check of type known at compile time.
+void isComment(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
 
 NODE_TYPE_CASTS(Comment)
 
diff --git a/Source/WebCore/dom/ContainerNode.h b/Source/WebCore/dom/ContainerNode.h
index 8e508248..4a19777 100644
--- a/Source/WebCore/dom/ContainerNode.h
+++ b/Source/WebCore/dom/ContainerNode.h
@@ -170,32 +170,10 @@
     Node* m_lastChild;
 };
 
-inline ContainerNode* toContainerNode(Node* node)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isContainerNode());
-    return static_cast<ContainerNode*>(node);
-}
+inline bool isContainerNode(const Node& node) { return node.isContainerNode(); }
+void isContainerNode(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const ContainerNode* toContainerNode(const Node* node)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isContainerNode());
-    return static_cast<const ContainerNode*>(node);
-}
-
-inline ContainerNode& toContainerNode(Node& node)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(node.isContainerNode());
-    return static_cast<ContainerNode&>(node);
-}
-inline const ContainerNode& toContainerNode(const Node& node)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(node.isContainerNode());
-    return static_cast<const ContainerNode&>(node);
-}
-
-// This will catch anyone doing an unnecessary cast.
-void toContainerNode(const ContainerNode*);
-void toContainerNode(const ContainerNode&);
+NODE_TYPE_CASTS(ContainerNode)
 
 inline ContainerNode::ContainerNode(Document* document, ConstructionType type)
     : Node(document, type)
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 107e08c..0743101 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -899,19 +899,19 @@
     case COMMENT_NODE:
         return createComment(importedNode->nodeValue());
     case ELEMENT_NODE: {
-        Element* oldElement = toElement(importedNode);
+        Element& oldElement = toElement(*importedNode);
         // FIXME: The following check might be unnecessary. Is it possible that
         // oldElement has mismatched prefix/namespace?
-        if (!hasValidNamespaceForElements(oldElement->tagQName())) {
+        if (!hasValidNamespaceForElements(oldElement.tagQName())) {
             ec = NAMESPACE_ERR;
             return nullptr;
         }
-        RefPtr<Element> newElement = createElement(oldElement->tagQName(), false);
 
-        newElement->cloneDataFromElement(*oldElement);
+        RefPtr<Element> newElement = createElement(oldElement.tagQName(), false);
+        newElement->cloneDataFromElement(oldElement);
 
         if (deep) {
-            for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+            for (Node* oldChild = oldElement.firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
                 RefPtr<Node> newChild = importNode(oldChild, true, ec);
                 if (ec)
                     return nullptr;
@@ -924,17 +924,17 @@
         return newElement.release();
     }
     case ATTRIBUTE_NODE:
-        return Attr::create(*this, QualifiedName(nullAtom, static_cast<Attr*>(importedNode)->name(), nullAtom), static_cast<Attr*>(importedNode)->value());
+        return Attr::create(*this, QualifiedName(nullAtom, toAttr(*importedNode).name(), nullAtom), toAttr(*importedNode).value());
     case DOCUMENT_FRAGMENT_NODE: {
         if (importedNode->isShadowRoot()) {
             // ShadowRoot nodes should not be explicitly importable.
             // Either they are imported along with their host node, or created implicitly.
             break;
         }
-        DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode);
+        DocumentFragment& oldFragment = toDocumentFragment(*importedNode);
         RefPtr<DocumentFragment> newFragment = createDocumentFragment();
         if (deep) {
-            for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+            for (Node* oldChild = oldFragment.firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
                 RefPtr<Node> newChild = importNode(oldChild, true, ec);
                 if (ec)
                     return nullptr;
@@ -983,7 +983,7 @@
         ec = NOT_SUPPORTED_ERR;
         return nullptr;
     case ATTRIBUTE_NODE: {                   
-        Attr& attr = static_cast<Attr&>(*source);
+        Attr& attr = toAttr(*source);
         if (attr.ownerElement())
             attr.ownerElement()->removeAttributeNode(&attr, ec);
         attr.setSpecified(true);
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index 46dbf12..a714901 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -1622,13 +1622,13 @@
     return static_cast<const Document*>(scriptExecutionContext);
 }
 
-inline bool isDocument(const Node& node)
-{
-    return node.isDocumentNode();
-}
+inline bool isDocument(const Node& node) { return node.isDocumentNode(); }
+void isDocument(const Document&); // Catch unnecessary runtime check of type known at compile time.
 
 NODE_TYPE_CASTS(Document)
 
+#define DOCUMENT_TYPE_CASTS(ToClassName) TYPE_CASTS_BASE(ToClassName, Document)
+
 } // namespace WebCore
 
 namespace WTF {
diff --git a/Source/WebCore/dom/DocumentFragment.h b/Source/WebCore/dom/DocumentFragment.h
index 796f8c0..bde5d5f 100644
--- a/Source/WebCore/dom/DocumentFragment.h
+++ b/Source/WebCore/dom/DocumentFragment.h
@@ -49,6 +49,11 @@
     virtual bool childTypeAllowed(NodeType) const OVERRIDE;
 };
 
+inline bool isDocumentFragment(const Node& node) { return node.isDocumentFragment(); }
+void isDocumentFragment(const DocumentFragment&); // Catch unnecessary runtime check of type known at compile time.
+
+NODE_TYPE_CASTS(DocumentFragment)
+
 } //namespace
 
 #endif
diff --git a/Source/WebCore/dom/DocumentStyleSheetCollection.cpp b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
index a096dad..f965244 100644
--- a/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
+++ b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
@@ -268,7 +268,7 @@
         if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
             // Processing instruction (XML documents only).
             // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
-            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
+            ProcessingInstruction* pi = toProcessingInstruction(n);
             sheet = pi->sheet();
 #if ENABLE(XSLT)
             // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
@@ -315,11 +315,12 @@
             else
 #endif
             {
-                if (e->hasTagName(linkTag))
-                    sheet = static_cast<HTMLLinkElement*>(n)->sheet();
-                else
+                if (isHTMLLinkElement(e))
+                    sheet = toHTMLLinkElement(n)->sheet();
+                else {
                     // <STYLE> element
                     sheet = toHTMLStyleElement(e)->sheet();
+                }
             }
             // Check to see if this sheet belongs to a styleset
             // (thus making it PREFERRED or ALTERNATE rather than
diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp
index 71be3b0..7cf3f58 100644
--- a/Source/WebCore/dom/NamedNodeMap.cpp
+++ b/Source/WebCore/dom/NamedNodeMap.cpp
@@ -93,7 +93,7 @@
         return 0;
     }
 
-    return m_element->setAttributeNode(static_cast<Attr*>(node), ec);
+    return m_element->setAttributeNode(toAttr(node), ec);
 }
 
 PassRefPtr<Node> NamedNodeMap::setNamedItemNS(Node* node, ExceptionCode& ec)
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index e29536e..ff3b392 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -1446,8 +1446,8 @@
     if (otherNode == this)
         return DOCUMENT_POSITION_EQUIVALENT;
     
-    Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(this) : 0;
-    Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(otherNode) : 0;
+    Attr* attr1 = isAttributeNode() ? toAttr(this) : nullptr;
+    Attr* attr2 = otherNode->isAttributeNode() ? toAttr(otherNode) : nullptr;
     
     Node* start1 = attr1 ? attr1->ownerElement() : this;
     Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index cedb1aa..2bfd0cb 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -718,29 +718,31 @@
     return parentNode();
 }
 
-#define NODE_TYPE_CASTS(NodeClassName) \
-inline const NodeClassName* to##NodeClassName(const Node* node) \
+#define TYPE_CASTS_BASE(ToClassName, FromClassName) \
+inline const ToClassName* to##ToClassName(const FromClassName* object) \
 { \
-    ASSERT_WITH_SECURITY_IMPLICATION(!node || is##NodeClassName(*node)); \
-    return static_cast<const NodeClassName*>(node); \
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || is##ToClassName(*object)); \
+    return static_cast<const ToClassName*>(object); \
 } \
-inline NodeClassName* to##NodeClassName(Node* node) \
+inline ToClassName* to##ToClassName(FromClassName* object) \
 { \
-    ASSERT_WITH_SECURITY_IMPLICATION(!node || is##NodeClassName(*node)); \
-    return static_cast<NodeClassName*>(node); \
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || is##ToClassName(*object)); \
+    return static_cast<ToClassName*>(object); \
 } \
-inline const NodeClassName& to##NodeClassName(const Node& node) \
+inline const ToClassName& to##ToClassName(const FromClassName& object) \
 { \
-    ASSERT_WITH_SECURITY_IMPLICATION(is##NodeClassName(node)); \
-    return static_cast<const NodeClassName&>(node); \
+    ASSERT_WITH_SECURITY_IMPLICATION(is##ToClassName(object)); \
+    return static_cast<const ToClassName&>(object); \
 } \
-inline NodeClassName& to##NodeClassName(Node& node) \
+inline ToClassName& to##ToClassName(FromClassName& object) \
 { \
-    ASSERT_WITH_SECURITY_IMPLICATION(is##NodeClassName(node)); \
-    return static_cast<NodeClassName&>(node); \
+    ASSERT_WITH_SECURITY_IMPLICATION(is##ToClassName(object)); \
+    return static_cast<ToClassName&>(object); \
 } \
-void to##NodeClassName(const NodeClassName*); \
-void to##NodeClassName(const NodeClassName&);
+void to##ToClassName(const ToClassName*); \
+void to##ToClassName(const ToClassName&);
+
+#define NODE_TYPE_CASTS(ToClassName) TYPE_CASTS_BASE(ToClassName, Node)
 
 } // namespace WebCore
 
diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp
index 3f3410f..68a4714 100644
--- a/Source/WebCore/dom/Range.cpp
+++ b/Source/WebCore/dom/Range.cpp
@@ -650,9 +650,9 @@
     case Node::TEXT_NODE:
     case Node::CDATA_SECTION_NODE:
     case Node::COMMENT_NODE:
-        return static_cast<CharacterData*>(node)->length();
+        return toCharacterData(node)->length();
     case Node::PROCESSING_INSTRUCTION_NODE:
-        return static_cast<ProcessingInstruction*>(node)->data().length();
+        return toProcessingInstruction(node)->data().length();
     case Node::ELEMENT_NODE:
     case Node::ATTRIBUTE_NODE:
     case Node::ENTITY_REFERENCE_NODE:
@@ -776,8 +776,7 @@
         data->deleteData(0, startOffset, ec);
 }
 
-PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment,
-    Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
+PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment, Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
 {
     ASSERT(container);
     ASSERT(startOffset <= endOffset);
@@ -788,7 +787,7 @@
     case Node::TEXT_NODE:
     case Node::CDATA_SECTION_NODE:
     case Node::COMMENT_NODE:
-        ASSERT(endOffset <= static_cast<CharacterData*>(container)->length());
+        ASSERT(endOffset <= toCharacterData(container)->length());
         if (action == Extract || action == Clone) {
             RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true));
             deleteCharacterData(c, startOffset, endOffset, ec);
@@ -799,10 +798,10 @@
                 result = c.release();
         }
         if (action == Extract || action == Delete)
-            static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, ec);
+            toCharacterData(container)->deleteData(startOffset, endOffset - startOffset, ec);
         break;
     case Node::PROCESSING_INSTRUCTION_NODE:
-        ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length());
+        ASSERT(endOffset <= toProcessingInstruction(container)->data().length());
         if (action == Extract || action == Clone) {
             RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true));
             c->setData(c->data().substring(startOffset, endOffset - startOffset), ec);
@@ -813,7 +812,7 @@
                 result = c.release();
         }
         if (action == Extract || action == Delete) {
-            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container);
+            ProcessingInstruction* pi = toProcessingInstruction(container);
             String data(pi->data());
             data.remove(startOffset, endOffset - startOffset);
             pi->setData(data, ec);
@@ -837,7 +836,7 @@
         }
 
         Node* n = container->firstChild();
-        Vector<RefPtr<Node> > nodes;
+        Vector<RefPtr<Node>> nodes;
         for (unsigned i = startOffset; n && i; i--)
             n = n->nextSibling();
         for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling())
@@ -1143,11 +1142,11 @@
         case Node::CDATA_SECTION_NODE:
         case Node::COMMENT_NODE:
         case Node::TEXT_NODE:
-            if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length())
+            if (static_cast<unsigned>(offset) > toCharacterData(n)->length())
                 ec = INDEX_SIZE_ERR;
             return 0;
         case Node::PROCESSING_INSTRUCTION_NODE:
-            if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length())
+            if (static_cast<unsigned>(offset) > toProcessingInstruction(n)->data().length())
                 ec = INDEX_SIZE_ERR;
             return 0;
         case Node::ATTRIBUTE_NODE:
diff --git a/Source/WebCore/dom/Text.h b/Source/WebCore/dom/Text.h
index 2c87621..5910a6a 100644
--- a/Source/WebCore/dom/Text.h
+++ b/Source/WebCore/dom/Text.h
@@ -72,9 +72,9 @@
 #endif
 };
 
+inline bool isText(const Node& node) { return node.isTextNode(); }
 void isText(const Text&); // Catch unnecessary runtime check of type known at compile time.
 void isText(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isText(const Node& node) { return node.isTextNode(); }
 
 NODE_TYPE_CASTS(Text)
 
diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp
index f7fc4a8..fa3f7b6 100644
--- a/Source/WebCore/editing/ApplyStyleCommand.cpp
+++ b/Source/WebCore/editing/ApplyStyleCommand.cpp
@@ -1325,8 +1325,8 @@
 
     Node* nextSibling = endNode->nextSibling();
     if (nextSibling && areIdenticalElements(endNode, nextSibling)) {
-        Element* nextElement = static_cast<Element *>(nextSibling);
-        Element* element = static_cast<Element *>(endNode);
+        Element* nextElement = toElement(nextSibling);
+        Element* element = toElement(endNode);
         Node* nextChild = nextElement->firstChild();
 
         mergeIdenticalElements(element, nextElement);
diff --git a/Source/WebCore/editing/CompositeEditCommand.cpp b/Source/WebCore/editing/CompositeEditCommand.cpp
index 2e68109..33906d2 100644
--- a/Source/WebCore/editing/CompositeEditCommand.cpp
+++ b/Source/WebCore/editing/CompositeEditCommand.cpp
@@ -1010,7 +1010,7 @@
         for (size_t i = ancestors.size(); i != 0; --i) {
             Node* item = ancestors[i - 1].get();
             RefPtr<Node> child = item->cloneNode(isTableElement(item));
-            appendNode(child, static_cast<Element *>(lastNode.get()));
+            appendNode(child, toElement(lastNode.get()));
             lastNode = child.release();
         }
     }
diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp
index ad563e9..0146216 100644
--- a/Source/WebCore/editing/Editor.cpp
+++ b/Source/WebCore/editing/Editor.cpp
@@ -463,7 +463,7 @@
     if (fragment) {
         Node* child = fragment->firstChild();
         if (child && fragment->lastChild() == child && child->isCharacterDataNode())
-            return client()->shouldInsertText(static_cast<CharacterData*>(child)->data(), replacingDOMRange.get(), givenAction);        
+            return client()->shouldInsertText(toCharacterData(child)->data(), replacingDOMRange.get(), givenAction);
     }
 
     return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
diff --git a/Source/WebCore/editing/FrameSelection.cpp b/Source/WebCore/editing/FrameSelection.cpp
index f6d3a2a..a5dbe31 100644
--- a/Source/WebCore/editing/FrameSelection.cpp
+++ b/Source/WebCore/editing/FrameSelection.cpp
@@ -1464,10 +1464,10 @@
 #endif
 }
 
-void FrameSelection::debugRenderer(RenderObject *r, bool selected) const
+void FrameSelection::debugRenderer(RenderObject* r, bool selected) const
 {
     if (r->node()->isElementNode()) {
-        Element* element = static_cast<Element *>(r->node());
+        Element* element = toElement(r->node());
         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
     } else if (r->isText()) {
         RenderText* textRenderer = toRenderText(r);
diff --git a/Source/WebCore/html/HTMLDocument.h b/Source/WebCore/html/HTMLDocument.h
index 57a07ec..842ba69 100644
--- a/Source/WebCore/html/HTMLDocument.h
+++ b/Source/WebCore/html/HTMLDocument.h
@@ -92,32 +92,10 @@
     DocumentOrderedMap m_windowNamedItem;
 };
 
-inline HTMLDocument* toHTMLDocument(Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isHTMLDocument());
-    return static_cast<HTMLDocument*>(document);
-}
+inline bool isHTMLDocument(const Document& document) { return document.isHTMLDocument(); }
+void isHTMLDocument(const HTMLDocument&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const HTMLDocument* toHTMLDocument(const Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isHTMLDocument());
-    return static_cast<const HTMLDocument*>(document);
-}
-
-inline HTMLDocument& toHTMLDocument(Document& document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(document.isHTMLDocument());
-    return static_cast<HTMLDocument&>(document);
-}
-
-inline const HTMLDocument& toHTMLDocument(const Document& document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(document.isHTMLDocument());
-    return static_cast<const HTMLDocument&>(document);
-}
-// This will catch anyone doing an unnecessary cast.
-void toHTMLDocument(const HTMLDocument*);
-void toHTMLDocument(const HTMLDocument&);
+DOCUMENT_TYPE_CASTS(HTMLDocument)
 
 } // namespace WebCore
 
diff --git a/Source/WebCore/html/HTMLLinkElement.h b/Source/WebCore/html/HTMLLinkElement.h
index 825ff7a..2a6ba0f 100644
--- a/Source/WebCore/html/HTMLLinkElement.h
+++ b/Source/WebCore/html/HTMLLinkElement.h
@@ -137,6 +137,8 @@
     PendingSheetType m_pendingSheetType;
 };
 
+NODE_TYPE_CASTS(HTMLLinkElement)
+
 } //namespace
 
 #endif
diff --git a/Source/WebCore/html/HTMLTagNames.in b/Source/WebCore/html/HTMLTagNames.in
index c583848..11f5ccd 100644
--- a/Source/WebCore/html/HTMLTagNames.in
+++ b/Source/WebCore/html/HTMLTagNames.in
@@ -75,7 +75,7 @@
 layer interfaceName=HTMLElement
 legend generateTypeHelpers
 li interfaceName=HTMLLIElement
-link constructorNeedsCreatedByParser
+link constructorNeedsCreatedByParser, generateTypeHelpers
 listing interfaceName=HTMLPreElement
 main interfaceName=HTMLElement
 map generateTypeHelpers
diff --git a/Source/WebCore/html/ImageDocument.h b/Source/WebCore/html/ImageDocument.h
index ed5339c..c54a281 100644
--- a/Source/WebCore/html/ImageDocument.h
+++ b/Source/WebCore/html/ImageDocument.h
@@ -71,20 +71,10 @@
     bool m_shouldShrinkImage;
 };
 
-inline ImageDocument* toImageDocument(Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isImageDocument());
-    return static_cast<ImageDocument*>(document);
-}
+inline bool isImageDocument(const Document& document) { return document.isImageDocument(); }
+void isImageDocument(const ImageDocument&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const ImageDocument* toImageDocument(const Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isImageDocument());
-    return static_cast<const ImageDocument*>(document);
-}
-
-// This will catch anyone doing an unnecessary cast.
-void toImageDocument(const ImageDocument*);
+DOCUMENT_TYPE_CASTS(ImageDocument)
 
 }
 
diff --git a/Source/WebCore/html/MediaDocument.h b/Source/WebCore/html/MediaDocument.h
index 5f611b0..9b972df 100644
--- a/Source/WebCore/html/MediaDocument.h
+++ b/Source/WebCore/html/MediaDocument.h
@@ -54,33 +54,10 @@
     Timer<MediaDocument> m_replaceMediaElementTimer;
 };
 
-inline MediaDocument* toMediaDocument(Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isMediaDocument());
-    return static_cast<MediaDocument*>(document);
-}
+inline bool isMediaDocument(const Document& document) { return document.isMediaDocument(); }
+void isMediaDocument(const MediaDocument&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const MediaDocument* toMediaDocument(const Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isMediaDocument());
-    return static_cast<const MediaDocument*>(document);
-}
-
-inline MediaDocument& toMediaDocument(Document& document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(document.isMediaDocument());
-    return static_cast<MediaDocument&>(document);
-}
-
-inline const MediaDocument& toMediaDocument(const Document& document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(document.isMediaDocument());
-    return static_cast<const MediaDocument&>(document);
-}
-
-// This will catch anyone doing an unnecessary cast.
-void toMediaDocument(const MediaDocument*);
-void toMediaDocument(const MediaDocument&);
+DOCUMENT_TYPE_CASTS(MediaDocument)
 
 }
 
diff --git a/Source/WebCore/html/PluginDocument.h b/Source/WebCore/html/PluginDocument.h
index 20e4c8c..fcd3543 100644
--- a/Source/WebCore/html/PluginDocument.h
+++ b/Source/WebCore/html/PluginDocument.h
@@ -61,21 +61,11 @@
     RefPtr<HTMLPlugInElement> m_pluginElement;
 };
 
-inline PluginDocument* toPluginDocument(Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isPluginDocument());
-    return static_cast<PluginDocument*>(document);
-}
+inline bool isPluginDocument(const Document& document) { return document.isPluginDocument(); }
+void isPluginDocument(const PluginDocument&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const PluginDocument* toPluginDocument(const Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isPluginDocument());
-    return static_cast<const PluginDocument*>(document);
-}
+DOCUMENT_TYPE_CASTS(PluginDocument)
 
-// This will catch anyone doing an unnecessary cast.
-void toPluginDocument(const PluginDocument*);
-    
 }
 
 #endif // PluginDocument_h
diff --git a/Source/WebCore/html/parser/HTMLConstructionSite.cpp b/Source/WebCore/html/parser/HTMLConstructionSite.cpp
index 2b80c5d..80f268a 100644
--- a/Source/WebCore/html/parser/HTMLConstructionSite.cpp
+++ b/Source/WebCore/html/parser/HTMLConstructionSite.cpp
@@ -505,7 +505,7 @@
     if (previousChild && previousChild->isTextNode()) {
         // FIXME: We're only supposed to append to this text node if it
         // was the last text node inserted by the parser.
-        CharacterData* textNode = static_cast<CharacterData*>(previousChild);
+        Text* textNode = toText(previousChild);
         currentPosition = textNode->parserAppendData(characters, 0, lengthLimit);
     }
 
@@ -637,7 +637,7 @@
         // and instead use the DocumentFragment as a root node. So we must treat the root node (DocumentFragment) as if it is a html element here.
         bool parentCanBeFosterParent = parent && (parent->isElementNode() || (m_isParsingFragment && parent == m_openElements.rootNode()));
 #if ENABLE(TEMPLATE_ELEMENT)
-        parentCanBeFosterParent = parentCanBeFosterParent || (parent && parent->isDocumentFragment() && static_cast<DocumentFragment*>(parent)->isTemplateContent());
+        parentCanBeFosterParent = parentCanBeFosterParent || (parent && parent->isDocumentFragment() && toDocumentFragment(parent)->isTemplateContent());
 #endif
         if (parentCanBeFosterParent) {
             task.parent = parent;
diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp
index ad7d45c..9a8ebfd 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.cpp
+++ b/Source/WebCore/html/shadow/MediaControlElements.cpp
@@ -324,7 +324,7 @@
         Node* child = childNode(i);
         if (!child || !child->isElementNode())
             continue;
-        Element* element = static_cast<Element*>(child);
+        Element* element = toElement(child);
         if (element->shadowPseudoId() != getMediaControlTimeRemainingDisplayElementShadowPseudoId()
             && element->shadowPseudoId() != getMediaControlCurrentTimeDisplayElementShadowPseudoId())
             continue;
diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp
index 6223625..b661c5e 100644
--- a/Source/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp
@@ -987,8 +987,8 @@
                 if (ec)
                     break;
 
-                if (node->nodeType() == Node::ATTRIBUTE_NODE)
-                    node = static_cast<Attr*>(node)->ownerElement();
+                if (node->isAttributeNode())
+                    node = toAttr(node)->ownerElement();
                 resultCollector.add(node);
             }
         }
@@ -1427,12 +1427,12 @@
         value->setBaseURL(documentBaseURLString(document));
         value->setXmlVersion(document->xmlVersion());
     } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
-        DocumentType* docType = static_cast<DocumentType*>(node);
+        DocumentType* docType = toDocumentType(node);
         value->setPublicId(docType->publicId());
         value->setSystemId(docType->systemId());
         value->setInternalSubset(docType->internalSubset());
     } else if (node->isAttributeNode()) {
-        Attr* attribute = static_cast<Attr*>(node);
+        Attr* attribute = toAttr(node);
         value->setName(attribute->name());
         value->setValue(attribute->value());
     }
diff --git a/Source/WebCore/svg/SVGDocument.h b/Source/WebCore/svg/SVGDocument.h
index 0a660c2..186b44e 100644
--- a/Source/WebCore/svg/SVGDocument.h
+++ b/Source/WebCore/svg/SVGDocument.h
@@ -56,20 +56,10 @@
     FloatPoint m_translate;
 };
 
-inline SVGDocument* toSVGDocument(Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isSVGDocument());
-    return static_cast<SVGDocument*>(document);
-}
+inline bool isSVGDocument(const Document& document) { return document.isSVGDocument(); }
+void isSVGDocument(const SVGDocument&); // Catch unnecessary runtime check of type known at compile time.
 
-inline const SVGDocument* toSVGDocument(const Document* document)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!document || document->isSVGDocument());
-    return static_cast<const SVGDocument*>(document);
-}
-
-// This will catch anyone doing an unnecessary cast.
-void toSVGDocument(const SVGDocument*);
+DOCUMENT_TYPE_CASTS(SVGDocument)
 
 } // namespace WebCore
 
diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp
index bc59325..41f7ddd 100644
--- a/Source/WebCore/xml/XPathFunctions.cpp
+++ b/Source/WebCore/xml/XPathFunctions.cpp
@@ -358,7 +358,7 @@
     // The local part of an XPath expanded-name matches DOM local name for most node types, except for namespace nodes and processing instruction nodes.
     ASSERT(node->nodeType() != Node::XPATH_NAMESPACE_NODE); // Not supported yet.
     if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
-        return static_cast<ProcessingInstruction*>(node)->target();
+        return toProcessingInstruction(node)->target();
     return node->localName().string();
 }
 
diff --git a/Source/WebCore/xml/XPathNodeSet.cpp b/Source/WebCore/xml/XPathNodeSet.cpp
index e5a6a92..df6633f 100644
--- a/Source/WebCore/xml/XPathNodeSet.cpp
+++ b/Source/WebCore/xml/XPathNodeSet.cpp
@@ -96,7 +96,7 @@
         // FIXME: namespace nodes are not implemented.
         for (unsigned i = sortedEnd; i < to; ++i) {
             Node* n = parentMatrix[i][0];
-            if (n->isAttributeNode() && static_cast<Attr*>(n)->ownerElement() == commonAncestor)
+            if (n->isAttributeNode() && toAttr(n)->ownerElement() == commonAncestor)
                 parentMatrix[i].swap(parentMatrix[sortedEnd++]);
         }
         if (sortedEnd != from) {
@@ -159,7 +159,7 @@
         Node* n = m_nodes[i].get();
         parentsVector.append(n);
         if (n->isAttributeNode()) {
-            n = static_cast<Attr*>(n)->ownerElement();
+            n = toAttr(n)->ownerElement();
             parentsVector.append(n);
             containsAttributeNodes = true;
         }
@@ -181,7 +181,7 @@
 static Node* findRootNode(Node* node)
 {
     if (node->isAttributeNode())
-        node = static_cast<Attr*>(node)->ownerElement();
+        node = toAttr(node)->ownerElement();
     if (node->inDocument())
         node = &node->document();
     else {