Bug 450160 - DOMImplementation createDocument does not create an HTML document, r+sr=bz
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sat, 20 Sep 2008 21:55:04 +0300
changeset 19464 8fbe05371cc3e56e926a9066eb556bf1a05c0545
parent 19463 29ca9b9f5d3cd3a97058cbdd9732fad06f1be0e7
child 19465 d576ce1f70422c2503f4410b015d2c16e7328655
push id2252
push useropettay@mozilla.com
push dateSat, 20 Sep 2008 18:58:11 +0000
treeherderautoland@8fbe05371cc3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs450160
milestone1.9.1b1pre
Bug 450160 - DOMImplementation createDocument does not create an HTML document, r+sr=bz
content/base/test/Makefile.in
content/base/test/test_bug450160.html
content/html/document/src/nsHTMLDocument.h
content/html/document/src/nsIHTMLDocument.h
content/xml/document/src/nsXMLDocument.cpp
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -205,16 +205,17 @@ include $(topsrcdir)/config/rules.mk
 		file_bug445225_multipart.txt \
 		file_bug445225_multipart.txt^headers^ \
 		test_title.html \
 		test_bug453521.html \
 		test_bug391728.html \
 		file_bug391728.html \
 		file_bug391728_2.html \
 		test_bug368972.html \
+		test_bug450160.html \
 		test_bug454326.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 check::
 	@$(EXIT_ON_ERROR) \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug450160.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=450160
+-->
+<head>
+  <title>Test for Bug 450160</title>
+  <script type="application/javascript" src="/MochiKit/MochiKit.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=450160">Mozilla Bug 450160</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 450160 **/
+
+
+function testHTMLDocuments(ids, isXHTML) {
+  for (var i = 0; i < ids.length; ++i) {
+    var docType1 =
+      document.implementation.createDocumentType(isXHTML ? "html" : "HTML",
+                                                 ids[i],
+                                                 null);
+    ok(docType1, "No doctype?");
+    ok(!docType1.ownerDocument, "docType shouldn't have ownerDocument!\n");
+    var doc1 = document.implementation.createDocument(null, null, docType1);
+    is(docType1.ownerDocument, doc1, "docType should have ownerDocument!\n");
+    ok(!doc1.documentElement, "Document shouldn't have document element!");
+    is(doc1.body, null, "Shouldn't have .body!");
+    ok(doc1 instanceof Components.interfaces.nsIDOMHTMLDocument,
+       "Document should be an HTML document!");
+    ok(!(doc1 instanceof Components.interfaces.nsIDOMSVGDocument),
+       "Document shouldn't be an SVG document!");
+
+    var docType2 =
+      document.implementation.createDocumentType(isXHTML ? "html" : "HTML",
+                                                 ids[i],
+                                                 null);
+    var doc2 = document.implementation.createDocument(
+      "http://www.w3.org/1999/xhtml", "html", docType2);
+    is(docType2.ownerDocument, doc2, "docType should have ownerDocument!\n");
+    ok(doc2.documentElement, "Document should have document element!");
+    is(doc2.documentElement.localName, "html", "Wrong document element!");
+    is(doc2.body, null, "Shouldn't have .body!");
+    doc2.documentElement.appendChild(doc2.createElement("body"));
+    is(doc2.body, doc2.documentElement.firstChild, "Should have .body!");
+    if (isXHTML) {
+      doc2.body.appendChild(doc2.createElementNS("http://www.w3.org/1999/xhtml", "form"));
+    } else {
+      doc2.body.appendChild(doc2.createElement("form"));
+    }
+    is(doc2.forms.length, 1, "Form wasn't added .forms");
+  }
+}
+
+function testSVGDocument() {
+  var docType1 =
+      document.implementation.createDocumentType("svg",
+                                                 "-//W3C//DTD SVG 1.1//EN",
+                                                 null);
+  ok(docType1, "No doctype?");
+  ok(!docType1.ownerDocument, "docType shouldn't have ownerDocument!\n");
+  var doc1 = document.implementation.createDocument(null, null, docType1);
+  is(docType1.ownerDocument, doc1, "docType should have ownerDocument!\n");
+  ok(!doc1.documentElement, "Document shouldn't have document element!");
+  ok(!(doc1 instanceof Components.interfaces.nsIDOMHTMLDocument),
+     "Document shouldn't be an HTML document!");
+  ok(doc1 instanceof Components.interfaces.nsIDOMSVGDocument,
+     "Document should be an SVG document!");
+
+  // SVG documents have .rootElement.
+  ok("rootElement" in doc1, "No .rootElement in document");
+
+  var docType2 =
+      document.implementation.createDocumentType("svg",
+                                                 "-//W3C//DTD SVG 1.1//EN",
+                                                 null);
+  var doc2 = document.implementation.createDocument("http://www.w3.org/2000/svg",
+                                                    "svg", docType2);
+  ok(doc2.documentElement, "Document should have document element!");
+  ok(doc2.rootElement, "Should have .rootElement in document");
+  is(doc2.rootElement.localName, "svg", "Wrong .rootElement!");
+}
+
+function testFooBarDocument() {
+  var docType1 =
+      document.implementation.createDocumentType("FooBar", "FooBar", null);
+  ok(docType1, "No doctype?");
+  ok(!docType1.ownerDocument, "docType shouldn't have ownerDocument!\n");
+  var doc1 = document.implementation.createDocument(null, null, docType1);
+  is(docType1.ownerDocument, doc1, "docType should have ownerDocument!\n");
+  ok(!doc1.documentElement, "Document shouldn't have document element!");
+  ok(!(doc1 instanceof Components.interfaces.nsIDOMHTMLDocument),
+     "Document shouldn't be an HTML document!");
+  ok(!(doc1 instanceof Components.interfaces.nsIDOMSVGDocument),
+     "Document shouldn't be an SVG document!");
+
+  var docType2 =
+      document.implementation.createDocumentType("FooBar", "FooBar", null);
+  var doc2 = document.implementation.createDocument("FooBarNS",
+                                                    "FooBar", docType2);
+  ok(doc2.documentElement, "Document should have document element!");
+  is(doc2.documentElement.namespaceURI, "FooBarNS", "Wrong namespaceURI!");
+  is(doc2.documentElement.localName, "FooBar", "Wrong localName!");
+}
+
+function testNullDocTypeDocument() {
+  var doc1 = document.implementation.createDocument(null, null, null);
+  ok(!doc1.documentElement, "Document shouldn't have document element!");
+  ok(!(doc1 instanceof Components.interfaces.nsIDOMHTMLDocument),
+     "Document shouldn't be an HTML document!");
+  ok(!(doc1 instanceof Components.interfaces.nsIDOMSVGDocument),
+     "Document shouldn't be an SVG document!");
+
+  var doc2 = document.implementation.createDocument("FooBarNS",
+                                                    "FooBar", null);
+  ok(doc2.documentElement, "Document should have document element!");
+  is(doc2.documentElement.namespaceURI, "FooBarNS", "Wrong namespaceURI!");
+  is(doc2.documentElement.localName, "FooBar", "Wrong localName!");
+}
+
+var htmlPublicIDs = 
+  [ "-//W3C//DTD HTML 4.01//EN",
+    "-//W3C//DTD HTML 4.01 Transitional//EN",
+    "-//W3C//DTD HTML 4.01 Frameset//EN",
+    "-//W3C//DTD HTML 4.0//EN",
+    "-//W3C//DTD HTML 4.0 Transitional//EN",
+    "-//W3C//DTD HTML 4.0 Frameset//EN" ];
+
+var xhtmlPublicIDs =
+ [ "-//W3C//DTD XHTML 1.0 Strict//EN",
+   "-//W3C//DTD XHTML 1.0 Transitional//EN",
+   "-//W3C//DTD XHTML 1.0 Frameset//EN" ];
+
+testHTMLDocuments(htmlPublicIDs, false);
+testHTMLDocuments(xhtmlPublicIDs, true);
+testSVGDocument();
+testFooBarDocument();
+testNullDocTypeDocument();
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -172,17 +172,17 @@ public:
 
   virtual void ScriptLoading(nsIScriptElement *aScript);
   virtual void ScriptExecuted(nsIScriptElement *aScript);
 
   virtual void AddedForm();
   virtual void RemovedForm();
   virtual PRInt32 GetNumFormsSynchronous();
   virtual void TearingDownEditor(nsIEditor *aEditor);
-
+  virtual void SetIsXHTML(PRBool aXHTML) { mIsRegularHTML = !aXHTML; }
   PRBool IsXHTML()
   {
     return !mIsRegularHTML;
   }
 
 #ifdef DEBUG
   virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
--- a/content/html/document/src/nsIHTMLDocument.h
+++ b/content/html/document/src/nsIHTMLDocument.h
@@ -50,20 +50,20 @@ class nsIDOMHTMLMapElement;
 class nsHTMLStyleSheet;
 class nsIStyleSheet;
 class nsICSSLoader;
 class nsIContent;
 class nsIDOMHTMLBodyElement;
 class nsIScriptElement;
 class nsIEditor;
 
-// 19d63a6c-cc94-499c-892a-955add772e10
+// 5a959364-a2f4-4cac-9a2c-957055dc3569
 #define NS_IHTMLDOCUMENT_IID \
-{ 0x19d63a6c, 0xcc94, 0x499c, \
-  { 0x89, 0x2a, 0x95, 0x5a, 0xdd, 0x77, 0x2e, 0x10 } }
+{ 0x5a959364, 0xa2f4, 0x4cac, \
+  { 0x9a, 0x2c, 0x95, 0x70, 0x55, 0xdc, 0x35, 0x69 } }
 
 
 /**
  * HTML document extensions to nsIDocument.
  */
 class nsIHTMLDocument : public nsISupports
 {
 public:
@@ -185,13 +185,15 @@ public:
    * anything <frameset>-related (like nsIDOMHTMLDocument::GetBody).
    */
   virtual nsIContent* GetBodyContentExternal() = 0;
 
   /**
    * Called when this nsIHTMLDocument's editor is destroyed.
    */
   virtual void TearingDownEditor(nsIEditor *aEditor) = 0;
+
+  virtual void SetIsXHTML(PRBool aXHTML) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLDocument, NS_IHTMLDOCUMENT_IID)
 
 #endif /* nsIHTMLDocument_h___ */
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -87,17 +87,17 @@
 #include "nsIScriptGlobalObjectOwner.h"
 #include "nsIJSContextStack.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsEventDispatcher.h"
 #include "nsNodeUtils.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
-
+#include "nsIHTMLDocument.h"
 
 // ==================================================================
 // =
 // ==================================================================
 
 
 nsresult
 NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
@@ -112,33 +112,69 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
   // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
   // since at least one caller (XMLHttpRequest) doesn't have decent args to
   // pass in.
   
   nsresult rv;
 
   *aInstancePtrResult = nsnull;
 
-  nsRefPtr<nsXMLDocument> doc = new nsXMLDocument();
-  if (!doc)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  rv = doc->Init();
+  nsCOMPtr<nsIDocument> d;
+  PRBool isHTML = PR_FALSE;
+  PRBool isXHTML = PR_FALSE;
+  if (aDoctype) {
+    nsAutoString publicId;
+    aDoctype->GetPublicId(publicId);
+    if (publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
+        publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
+        publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") ||
+        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") ||
+        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") ||
+        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) {
+      rv = NS_NewHTMLDocument(getter_AddRefs(d));
+      isHTML = PR_TRUE;
+    } else if (publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") ||
+               publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Transitional//EN") ||
+               publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) {
+      rv = NS_NewHTMLDocument(getter_AddRefs(d));
+      isHTML = PR_TRUE;
+      isXHTML = PR_TRUE;
+    }
+#ifdef MOZ_SVG
+    else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
+      rv = NS_NewSVGDocument(getter_AddRefs(d));
+    }
+#endif
+    // XXX Add support for XUL documents.
+    else {
+      rv = NS_NewXMLDocument(getter_AddRefs(d));
+    }
+  } else {
+    rv = NS_NewXMLDocument(getter_AddRefs(d));
+  }
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  if (isHTML) {
+    nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
+    NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
+    htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
+    htmlDoc->SetIsXHTML(isXHTML);
+  }
+  nsDocument* doc = static_cast<nsDocument*>(d.get());
   doc->SetLoadedAsData(aLoadedAsData);
   doc->nsDocument::SetDocumentURI(aDocumentURI);
   // Must set the principal first, since SetBaseURI checks it.
   doc->SetPrincipal(aPrincipal);
   doc->SetBaseURI(aBaseURI);
 
-  // XMLDocuments get to be UTF-8 by default, unlike the legacy HTML mess
+  // XMLDocuments and documents "created in memory" get to be UTF-8 by default,
+  // unlike the legacy HTML mess
   doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8"));
   
   if (aDoctype) {
     nsCOMPtr<nsIDOMNode> tmpNode;
     rv = doc->AppendChild(aDoctype, getter_AddRefs(tmpNode));
     NS_ENSURE_SUCCESS(rv, rv);
   }