Bug 1017932. Don't expose the XMLDocument bits on the return value of new Document(). r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 03 Jun 2014 11:38:37 -0400
changeset 205595 15aa216cebf99dc17be83984f29e7c6db700fe21
parent 205594 026bd94e5bd06146e64acd9d36c40da0fd35cea1
child 205596 019f004523b56b7bf8798bbf741778cc352689b0
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1017932
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1017932. Don't expose the XMLDocument bits on the return value of new Document(). r=peterv
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/base/test/mochitest.ini
content/base/test/test_document_constructor.html
content/xml/document/src/XMLDocument.cpp
content/xml/document/src/XMLDocument.h
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -133,17 +133,18 @@ typedef CallbackObjectHolder<NodeFilter,
 #define NS_IDOCUMENT_IID \
 { 0x0300e2e0, 0x24c9, 0x4ecf, \
   { 0x81, 0xec, 0x64, 0x26, 0x9a, 0x4b, 0xef, 0x18 } }
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
-  DocumentFlavorSVG // SVGDocument
+  DocumentFlavorSVG, // SVGDocument
+  DocumentFlavorPlain, // Just a Document
 };
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              NS_DEFINE_EVENT_STATE_MACRO(0)
 // Window activation status
 #define NS_DOCUMENT_STATE_WINDOW_INACTIVE         NS_DEFINE_EVENT_STATE_MACRO(1)
@@ -2680,17 +2681,18 @@ private:
   uint32_t                mMicroTaskLevel;
 };
 
 // XXX These belong somewhere else
 nsresult
 NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
 
 nsresult
-NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
+NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false,
+                  bool aIsPlainDocument = false);
 
 nsresult
 NS_NewSVGDocument(nsIDocument** aInstancePtrResult);
 
 nsresult
 NS_NewImageDocument(nsIDocument** aInstancePtrResult);
 
 nsresult
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -12062,17 +12062,17 @@ nsIDocument::Constructor(const GlobalObj
                       NullString(),
                       EmptyString(),
                       nullptr,
                       uri,
                       uri,
                       prin->GetPrincipal(),
                       true,
                       global,
-                      DocumentFlavorLegacyGuess);
+                      DocumentFlavorPlain);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
   doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
 
--- a/content/base/test/mochitest.ini
+++ b/content/base/test/mochitest.ini
@@ -561,16 +561,17 @@ run-if = os == 'linux'
 [test_copyimage.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' || e10s #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_copypaste.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_copypaste.xhtml]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183) b2g-debug(bug 904183) b2g-desktop(bug 904183)
 [test_createHTMLDocument.html]
 [test_declare_stylesheet_obsolete.html]
+[test_document_constructor.html]
 [test_domparser_null_char.html]
 [test_domparsing.html]
 [test_elementTraversal.html]
 [test_encodeToStringWithMaxLength.html]
 [test_fileapi.html]
 skip-if = e10s
 [test_fileapi_slice.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_document_constructor.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1017932
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1017932</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1017932 **/
+   var doc = new Document;
+   ok(doc instanceof Document, "Should have a document");
+   ok(!(doc instanceof XMLDocument), "Should not be an XMLDocument");
+   ok(!("load" in doc), "Should not have a load() method");
+   is(Object.getPrototypeOf(doc), Document.prototype,
+      "Should have the right proto");
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017932">Mozilla Bug 1017932</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/content/xml/document/src/XMLDocument.cpp
+++ b/content/xml/document/src/XMLDocument.cpp
@@ -45,16 +45,17 @@
 #include "nsNodeUtils.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIHTMLDocument.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/XMLDocumentBinding.h"
+#include "mozilla/dom/DocumentBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // ==================================================================
 // =
 // ==================================================================
 
@@ -82,17 +83,20 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
   nsCOMPtr<nsIDocument> d;
   bool isHTML = false;
   bool isXHTML = false;
   if (aFlavor == DocumentFlavorSVG) {
     rv = NS_NewSVGDocument(getter_AddRefs(d));
   } else if (aFlavor == DocumentFlavorHTML) {
     rv = NS_NewHTMLDocument(getter_AddRefs(d));
     isHTML = true;
+  } else if (aFlavor == DocumentFlavorPlain) {
+    rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true);
   } else if (aDoctype) {
+    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
     nsAutoString publicId, name;
     aDoctype->GetPublicId(publicId);
     if (publicId.IsEmpty()) {
       aDoctype->GetName(name);
     }
     if (name.EqualsLiteral("html") ||
         publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
         publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
@@ -112,16 +116,17 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
     else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
       rv = NS_NewSVGDocument(getter_AddRefs(d));
     }
     // XXX Add support for XUL documents.
     else {
       rv = NS_NewXMLDocument(getter_AddRefs(d));
     }
   } else {
+    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
     rv = NS_NewXMLDocument(getter_AddRefs(d));
   }
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
@@ -167,28 +172,30 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
 
   *aInstancePtrResult = doc;
   NS_ADDREF(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 nsresult
-NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
+NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData,
+                  bool aIsPlainDocument)
 {
   nsRefPtr<XMLDocument> doc = new XMLDocument();
 
   nsresult rv = doc->Init();
 
   if (NS_FAILED(rv)) {
     *aInstancePtrResult = nullptr;
     return rv;
   }
 
   doc->SetLoadedAsData(aLoadedAsData);
+  doc->mIsPlainDocument = aIsPlainDocument;
   doc.forget(aInstancePtrResult);
 
   return NS_OK;
 }
 
 nsresult
 NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
                   nsIURI* aDocumentURI,
@@ -592,20 +599,25 @@ XMLDocument::Clone(nsINodeInfo *aNodeInf
                "Can't import this document into another document!");
 
   nsRefPtr<XMLDocument> clone = new XMLDocument();
   nsresult rv = CloneDocHelper(clone);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // State from XMLDocument
   clone->mAsync = mAsync;
+  clone->mIsPlainDocument = mIsPlainDocument;
 
   return CallQueryInterface(clone.get(), aResult);
 }
 
 JSObject*
 XMLDocument::WrapNode(JSContext *aCx)
 {
+  if (mIsPlainDocument) {
+    return DocumentBinding::Wrap(aCx, this);
+  }
+
   return XMLDocumentBinding::Wrap(aCx, this);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/xml/document/src/XMLDocument.h
+++ b/content/xml/document/src/XMLDocument.h
@@ -65,23 +65,29 @@ public:
   using nsIDocument::GetLocation;
   // But then we need to also pull in the nsDocument XPCOM version
   // because nsXULDocument tries to forward to it.
   using nsDocument::GetLocation;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
 
+  friend nsresult (::NS_NewXMLDocument)(nsIDocument**, bool, bool);
+
+
   // mChannelIsPending indicates whether we're currently asynchronously loading
   // data from mChannel (via document.load() or normal load).  It's set to true
   // when we first find out about the channel (StartDocumentLoad) and set to
   // false in EndLoad or if ResetToURI() is called.  In the latter case our
   // mChannel is also cancelled.  Note that if this member is true, mChannel
   // cannot be null.
   bool mChannelIsPending;
   bool mAsync;
   bool mLoopingForSyncLoad;
+
+  // If true. we're really a Document, not an XMLDocument
+  bool mIsPlainDocument;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_XMLDocument_h