Bug 819239. Add the WebIDL API for HTMLDocument. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 25 Dec 2012 18:00:47 -0800
changeset 126133 f870d9cd5af11c2ebd229d9a261cbaa7da66f9ec
parent 126132 2aa1ecf204b1e8a408538301c0b727366c6803d1
child 126134 18a3309af87e03227e987c2be6929744751a1262
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs819239
milestone20.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 819239. Add the WebIDL API for HTMLDocument. r=peterv
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
dom/bindings/Bindings.conf
dom/webidl/HTMLDocument.webidl
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -937,63 +937,87 @@ nsHTMLDocument::GetDomainURI(nsIURI **aU
     principal->GetURI(aURI);
   }
 }
 
 
 NS_IMETHODIMP
 nsHTMLDocument::GetDomain(nsAString& aDomain)
 {
+  ErrorResult rv;
+  GetDomain(aDomain, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::GetDomain(nsAString& aDomain, ErrorResult& rv)
+{
   nsCOMPtr<nsIURI> uri;
   GetDomainURI(getter_AddRefs(uri));
 
   if (!uri) {
-    return NS_ERROR_FAILURE;
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
   }
 
   nsAutoCString hostName;
 
   if (NS_SUCCEEDED(uri->GetHost(hostName))) {
     CopyUTF8toUTF16(hostName, aDomain);
   } else {
     // If we can't get the host from the URI (e.g. about:, javascript:,
     // etc), just return an null string.
     SetDOMStringToNull(aDomain);
   }
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetDomain(const nsAString& aDomain)
 {
-  if (aDomain.IsEmpty())
-    return NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN;
+  ErrorResult rv;
+  SetDomain(aDomain, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
+{
+  if (aDomain.IsEmpty()) {
+    rv.Throw(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN);
+    return;
+  }
 
   // Create new URI
   nsCOMPtr<nsIURI> uri;
   GetDomainURI(getter_AddRefs(uri));
 
   if (!uri) {
-    return NS_ERROR_FAILURE;
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
   }
 
   nsAutoCString newURIString;
-  if (NS_FAILED(uri->GetScheme(newURIString)))
-    return NS_ERROR_FAILURE;
+  if (NS_FAILED(uri->GetScheme(newURIString))) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
   nsAutoCString path;
-  if (NS_FAILED(uri->GetPath(path)))
-    return NS_ERROR_FAILURE;
+  if (NS_FAILED(uri->GetPath(path))) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
   newURIString.AppendLiteral("://");
   AppendUTF16toUTF8(aDomain, newURIString);
   newURIString.Append(path);
 
   nsCOMPtr<nsIURI> newURI;
-  if (NS_FAILED(NS_NewURI(getter_AddRefs(newURI), newURIString)))
-    return NS_ERROR_FAILURE;
+  if (NS_FAILED(NS_NewURI(getter_AddRefs(newURI), newURIString))) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   // Check new domain - must be a superdomain of the current host
   // For example, a page from foo.bar.com may set domain to bar.com,
   // but not to ar.com, baz.com, or fi.foo.bar.com.
   nsAutoCString current, domain;
   if (NS_FAILED(uri->GetAsciiHost(current)))
     current.Truncate();
   if (NS_FAILED(newURI->GetAsciiHost(domain)))
@@ -1002,124 +1026,142 @@ nsHTMLDocument::SetDomain(const nsAStrin
   bool ok = current.Equals(domain);
   if (current.Length() > domain.Length() &&
       StringEndsWith(current, domain) &&
       current.CharAt(current.Length() - domain.Length() - 1) == '.') {
     // We're golden if the new domain is the current page's base domain or a
     // subdomain of it.
     nsCOMPtr<nsIEffectiveTLDService> tldService =
       do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
-    if (!tldService)
-      return NS_ERROR_NOT_AVAILABLE;
+    if (!tldService) {
+      rv.Throw(NS_ERROR_NOT_AVAILABLE);
+      return;
+    }
 
     nsAutoCString currentBaseDomain;
     ok = NS_SUCCEEDED(tldService->GetBaseDomain(uri, 0, currentBaseDomain));
     NS_ASSERTION(StringEndsWith(domain, currentBaseDomain) ==
                  (domain.Length() >= currentBaseDomain.Length()),
                  "uh-oh!  slight optimization wasn't valid somehow!");
     ok = ok && domain.Length() >= currentBaseDomain.Length();
   }
   if (!ok) {
     // Error: illegal domain
-    return NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN;
+    rv.Throw(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN);
+    return;
   }
 
-  return NodePrincipal()->SetDomain(newURI);
+  rv = NodePrincipal()->SetDomain(newURI);
 }
 
-Element*
+nsGenericHTMLElement*
 nsHTMLDocument::GetBody()
 {
   Element* body = GetBodyElement();
 
   if (body) {
     // There is a body element, return that as the body.
-    return body;
+    return static_cast<nsGenericHTMLElement*>(body);
   }
 
   // The document is most likely a frameset document so look for the
   // outer most frameset element
   nsRefPtr<nsContentList> nodeList =
     NS_GetContentList(this, kNameSpaceID_XHTML, NS_LITERAL_STRING("frameset"));
-
-  return nodeList->GetElementAt(0);
+  Element* frameset = nodeList->GetElementAt(0);
+  MOZ_ASSERT(!frameset || frameset->IsHTML());
+  return static_cast<nsGenericHTMLElement*>(frameset);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
 {
   *aBody = nullptr;
 
   nsIContent *body = GetBody();
 
   return body ? CallQueryInterface(body, aBody) : NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
 {
   nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
+  MOZ_ASSERT(!newBody || newBody->IsHTML(),
+             "How could we be an nsIContent but not actually HTML here?");
+  ErrorResult rv;
+  SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
+{
   Element* root = GetRootElement();
 
   // The body element must be either a body tag or a frameset tag. And we must
   // have a html root tag, otherwise GetBody will not return the newly set
   // body.
   if (!newBody || !(newBody->Tag() == nsGkAtoms::body ||
                     newBody->Tag() == nsGkAtoms::frameset) ||
       !root || !root->IsHTML() ||
       root->Tag() != nsGkAtoms::html) {
-    return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
+    rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
+    return;
   }
 
-  nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(root);
-  nsCOMPtr<nsIDOMNode> tmp;
-
   // Use DOM methods so that we pass through the appropriate security checks.
-  nsCOMPtr<nsIDOMNode> currentBody = do_QueryInterface(GetBodyElement());
+  Element* currentBody = GetBodyElement();
   if (currentBody) {
-    return rootElem->ReplaceChild(aBody, currentBody, getter_AddRefs(tmp));
+    root->ReplaceChild(*newBody, *currentBody, rv);
   }
 
-  return rootElem->AppendChild(aBody, getter_AddRefs(tmp));
+  root->AppendChild(*newBody, rv);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead)
 {
   *aHead = nullptr;
 
   Element* head = GetHeadElement();
 
   return head ? CallQueryInterface(head, aHead) : NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetImages(nsIDOMHTMLCollection** aImages)
 {
+  NS_ADDREF(*aImages = Images());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Images()
+{
   if (!mImages) {
     mImages = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::img, nsGkAtoms::img);
   }
-
-  *aImages = mImages;
-  NS_ADDREF(*aImages);
-
-  return NS_OK;
+  return mImages;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetApplets(nsIDOMHTMLCollection** aApplets)
 {
+  NS_ADDREF(*aApplets = Applets());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Applets()
+{
   if (!mApplets) {
     mApplets = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::applet, nsGkAtoms::applet);
   }
-
-  *aApplets = mApplets;
-  NS_ADDREF(*aApplets);
-
-  return NS_OK;
+  return mApplets;
 }
 
 bool
 nsHTMLDocument::MatchLinks(nsIContent *aContent, int32_t aNamespaceID,
                            nsIAtom* aAtom, void* aData)
 {
   nsIDocument* doc = aContent->GetCurrentDoc();
 
@@ -1147,24 +1189,27 @@ nsHTMLDocument::MatchLinks(nsIContent *a
   }
 
   return false;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetLinks(nsIDOMHTMLCollection** aLinks)
 {
+  NS_ADDREF(*aLinks = Links());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Links()
+{
   if (!mLinks) {
     mLinks = new nsContentList(this, MatchLinks, nullptr, nullptr);
   }
-
-  *aLinks = mLinks;
-  NS_ADDREF(*aLinks);
-
-  return NS_OK;
+  return mLinks;
 }
 
 bool
 nsHTMLDocument::MatchAnchors(nsIContent *aContent, int32_t aNamespaceID,
                              nsIAtom* aAtom, void* aData)
 {
   NS_ASSERTION(aContent->IsInDoc(),
                "This method should never be called on content nodes that "
@@ -1184,92 +1229,114 @@ nsHTMLDocument::MatchAnchors(nsIContent 
   }
 
   return false;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetAnchors(nsIDOMHTMLCollection** aAnchors)
 {
+  NS_ADDREF(*aAnchors = Anchors());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Anchors()
+{
   if (!mAnchors) {
     mAnchors = new nsContentList(this, MatchAnchors, nullptr, nullptr);
   }
-
-  *aAnchors = mAnchors;
-  NS_ADDREF(*aAnchors);
-
-  return NS_OK;
+  return mAnchors;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetScripts(nsIDOMHTMLCollection** aScripts)
 {
+  NS_ADDREF(*aScripts = Scripts());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Scripts()
+{
   if (!mScripts) {
     mScripts = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::script, nsGkAtoms::script);
   }
-
-  *aScripts = mScripts;
-  NS_ADDREF(*aScripts);
-
-  return NS_OK;
+  return mScripts;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetCookie(nsAString& aCookie)
 {
+  ErrorResult rv;
+  GetCookie(aCookie, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv)
+{
   aCookie.Truncate(); // clear current cookie in case service fails;
                       // no cookie isn't an error condition.
 
   if (mDisableCookieAccess) {
-    return NS_OK;
+    return;
   }
 
   // If the document's sandboxed origin flag is set, access to read cookies
   // is prohibited.
   if (mSandboxFlags & SANDBOXED_ORIGIN) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+    rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
   }
   
   // not having a cookie service isn't an error
   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
   if (service) {
     // Get a URI from the document principal. We use the original
     // codebase in case the codebase was changed by SetDomain
     nsCOMPtr<nsIURI> codebaseURI;
     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
 
     if (!codebaseURI) {
       // Document's principal is not a codebase (may be system), so
       // can't set cookies
 
-      return NS_OK;
+      return;
     }
 
     nsXPIDLCString cookie;
     service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie));
     // CopyUTF8toUTF16 doesn't handle error
     // because it assumes that the input is valid.
     nsContentUtils::ConvertStringFromCharset(NS_LITERAL_CSTRING("utf-8"),
                                              cookie, aCookie);
   }
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetCookie(const nsAString& aCookie)
 {
+  ErrorResult rv;
+  SetCookie(aCookie, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv)
+{
   if (mDisableCookieAccess) {
-    return NS_OK;
+    return;
   }
 
   // If the document's sandboxed origin flag is set, access to write cookies
   // is prohibited.
   if (mSandboxFlags & SANDBOXED_ORIGIN) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+    rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
   }
 
   // not having a cookie service isn't an error
   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
   if (service && mDocumentURI) {
     nsCOMPtr<nsIPrompt> prompt;
     nsCOMPtr<nsPIDOMWindow> window = GetWindow();
     if (window) {
@@ -1279,119 +1346,160 @@ nsHTMLDocument::SetCookie(const nsAStrin
     // The for getting the URI matches nsNavigator::GetCookieEnabled
     nsCOMPtr<nsIURI> codebaseURI;
     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
 
     if (!codebaseURI) {
       // Document's principal is not a codebase (may be system), so
       // can't set cookies
 
-      return NS_OK;
+      return;
     }
 
     NS_ConvertUTF16toUTF8 cookie(aCookie);
     service->SetCookieString(codebaseURI, prompt, cookie.get(), mChannel);
   }
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
                      const nsAString& aReplaceOrName,
                      const nsAString& aFeatures,
                      JSContext* cx, uint8_t aOptionalArgCount,
                      nsISupports** aReturn)
 {
-  NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
-               "XOW should have caught this!");
-
   // When called with 3 or more arguments, document.open() calls window.open().
   if (aOptionalArgCount > 2) {
-    nsCOMPtr<nsIDOMWindow> window = GetWindowInternal();
-    if (!window) {
-      return NS_OK;
-    }
-    nsCOMPtr<nsIDOMJSWindow> win = do_QueryInterface(window);
-    nsCOMPtr<nsIDOMWindow> newWindow;
-    nsresult rv = win->OpenJS(aContentTypeOrUrl, aReplaceOrName, aFeatures,
-                              getter_AddRefs(newWindow));
-    *aReturn = newWindow.forget().get();
-    return rv;
+    ErrorResult rv;
+    *aReturn = Open(cx, aContentTypeOrUrl, aReplaceOrName, aFeatures,
+                    false, rv).get();
+    return rv.ErrorCode();
+  }
+
+  nsString type;
+  if (aOptionalArgCount > 0) {
+    type = aContentTypeOrUrl;
+  } else {
+    type.AssignLiteral("text/html");
+  }
+  nsString replace;
+  if (aOptionalArgCount > 1) {
+    replace = aReplaceOrName;
   }
-
+  ErrorResult rv;
+  *aReturn = Open(cx, type, replace, rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsIDOMWindow>
+nsHTMLDocument::Open(JSContext* /* unused */,
+                     const nsAString& aURL,
+                     const nsAString& aName,
+                     const nsAString& aFeatures,
+                     bool aReplace,
+                     ErrorResult& rv)
+{
+  NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
+               "XOW should have caught this!");
+
+  nsCOMPtr<nsIDOMWindow> window = GetWindowInternal();
+  if (!window) {
+    rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+    return nullptr;
+  }
+  nsCOMPtr<nsIDOMJSWindow> win = do_QueryInterface(window);
+  nsCOMPtr<nsIDOMWindow> newWindow;
+  // XXXbz We ignore aReplace for now.
+  rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
+  return newWindow.forget();
+}
+
+already_AddRefed<nsIDocument>
+nsHTMLDocument::Open(JSContext* cx,
+                     const nsAString& aType,
+                     const nsAString& aReplace,
+                     ErrorResult& rv)
+{
+  NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
+               "XOW should have caught this!");
   if (!IsHTML() || mDisableDocWrite) {
     // No calling document.open() on XHTML
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+    rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
   }
 
   nsAutoCString contentType;
   contentType.AssignLiteral("text/html");
-  if (aOptionalArgCount > 0) {
-    nsAutoString type;
-    nsContentUtils::ASCIIToLower(aContentTypeOrUrl, type);
-    nsAutoCString actualType, dummy;
-    NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
-    if (!actualType.EqualsLiteral("text/html") &&
-        !type.EqualsLiteral("replace")) {
-      contentType.AssignLiteral("text/plain");
-    }
+
+  nsAutoString type;
+  nsContentUtils::ASCIIToLower(aType, type);
+  nsAutoCString actualType, dummy;
+  NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
+  if (!actualType.EqualsLiteral("text/html") &&
+      !type.EqualsLiteral("replace")) {
+    contentType.AssignLiteral("text/plain");
   }
 
   // If we already have a parser we ignore the document.open call.
   if (mParser || mParserAborted) {
     // The WHATWG spec says: "If the document has an active parser that isn't
     // a script-created parser, and the insertion point associated with that
     // parser's input stream is not undefined (that is, it does point to
     // somewhere in the input stream), then the method does nothing. Abort
     // these steps and return the Document object on which the method was
     // invoked."
     // Note that aborting a parser leaves the parser "active" with its
     // insertion point "not undefined". We track this using mParserAborted,
     // because aborting a parser nulls out mParser.
-    return NS_OK;
+    NS_ADDREF_THIS();
+    return this;
   }
 
   // No calling document.open() without a script global object
   if (!mScriptGlobalObject) {
-    return NS_OK;
+    NS_ADDREF_THIS();
+    return this;
   }
 
   nsPIDOMWindow* outer = GetWindow();
   if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) {
-    return NS_OK;
+    NS_ADDREF_THIS();
+    return this;
   }
 
   // check whether we're in the middle of unload.  If so, ignore this call.
   nsCOMPtr<nsIDocShell> shell = do_QueryReferent(mDocumentContainer);
   if (!shell) {
     // We won't be able to create a parser anyway.
-    return NS_OK;
+    NS_ADDREF_THIS();
+    return this;
   }
 
   bool inUnload;
   shell->GetIsInUnload(&inUnload);
   if (inUnload) {
-    return NS_OK;
+    NS_ADDREF_THIS();
+    return this;
   }
 
   // Note: We want to use GetDocumentFromContext here because this document
   // should inherit the security information of the document that's opening us,
   // (since if it's secure, then it's presumably trusted).
   nsCOMPtr<nsIDocument> callerDoc =
     do_QueryInterface(nsContentUtils::GetDocumentFromContext());
   if (!callerDoc) {
     // If we're called from C++ or in some other way without an originating
     // document we can't do a document.open w/o changing the principal of the
     // document to something like about:blank (as that's the only sane thing to
     // do when we don't know the origin of this call), and since we can't
     // change the principals of a document for security reasons we'll have to
     // refuse to go ahead with this call.
 
-    return NS_ERROR_DOM_SECURITY_ERR;
+    rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return nullptr;
   }
 
   // Grab a reference to the calling documents security info (if any)
   // and URIs as they may be lost in the call to Reset().
   nsCOMPtr<nsISupports> securityInfo = callerDoc->GetSecurityInfo();
   nsCOMPtr<nsIURI> uri = callerDoc->GetDocumentURI();
   nsCOMPtr<nsIURI> baseURI = callerDoc->GetBaseURI();
   nsCOMPtr<nsIPrincipal> callerPrincipal = callerDoc->NodePrincipal();
@@ -1416,30 +1524,32 @@ nsHTMLDocument::Open(const nsAString& aC
       callerDocURI->GetSpec(callerSpec);
     }
     if (thisURI) {
       thisURI->GetSpec(thisSpec);
     }
     printf("nsHTMLDocument::Open callerDoc %s this %s\n", callerSpec.get(), thisSpec.get());
 #endif
 
-    return NS_ERROR_DOM_SECURITY_ERR;
+    rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return nullptr;
   }
 
   // Stop current loads targeted at the window this document is in.
   if (mScriptGlobalObject) {
     nsCOMPtr<nsIContentViewer> cv;
     shell->GetContentViewer(getter_AddRefs(cv));
 
     if (cv) {
       bool okToUnload;
       if (NS_SUCCEEDED(cv->PermitUnload(false, &okToUnload)) && !okToUnload) {
         // We don't want to unload, so stop here, but don't throw an
         // exception.
-        return NS_OK;
+        NS_ADDREF_THIS();
+        return this;
       }
     }
 
     nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
     webnav->Stop(nsIWebNavigation::STOP_NETWORK);
 
     // The Stop call may have cancelled the onload blocker request or prevented
     // it from getting added, so we need to make sure it gets added to the
@@ -1448,117 +1558,128 @@ nsHTMLDocument::Open(const nsAString& aC
     EnsureOnloadBlocker();
   }
 
   // The open occurred after the document finished loading.
   // So we reset the document and create a new one.
   nsCOMPtr<nsIChannel> channel;
   nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocumentLoadGroup);
 
-  nsresult rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, group);
-
-  if (NS_FAILED(rv)) {
-    return rv;
+  rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, group);
+
+  if (rv.Failed()) {
+    return nullptr;
   }
 
   // We can't depend on channels implementing property bags, so do our
   // base URI manually after reset.
 
   // Set the caller principal, if any, on the channel so that we'll
   // make sure to use it when we reset.
   rv = channel->SetOwner(callerPrincipal);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return nullptr;
+  }
 
   if (callerChannel) {
     nsLoadFlags callerLoadFlags;
     rv = callerChannel->GetLoadFlags(&callerLoadFlags);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return nullptr;
+    }
 
     nsLoadFlags loadFlags;
     rv = channel->GetLoadFlags(&loadFlags);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return nullptr;
+    }
 
     loadFlags |= callerLoadFlags & nsIRequest::INHIBIT_PERSISTENT_CACHING;
 
     rv = channel->SetLoadFlags(loadFlags);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return nullptr;
+    }
   }
 
   // Before we reset the doc notify the globalwindow of the change,
   // but only if we still have a window (i.e. our window object the
   // current inner window in our outer window).
 
   // Hold onto ourselves on the offchance that we're down to one ref
-  nsCOMPtr<nsIDOMDocument> kungFuDeathGrip =
-    do_QueryInterface((nsIHTMLDocument*)this);
+  nsCOMPtr<nsIDocument> kungFuDeathGrip = this;
 
   nsPIDOMWindow *window = GetInnerWindow();
   if (window) {
     // Remember the old scope in case the call to SetNewDocument changes it.
     nsCOMPtr<nsIScriptGlobalObject> oldScope(do_QueryReferent(mScopeObject));
 
 #ifdef DEBUG
     bool willReparent = mWillReparent;
     mWillReparent = true;
 #endif
 
     // Should this pass true for aForceReuseInnerWindow?
     rv = window->SetNewDocument(this, nullptr, false);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return nullptr;
+    }
 
 #ifdef DEBUG
     mWillReparent = willReparent;
 #endif
 
     // Now make sure we're not flagged as the initial document anymore, now
     // that we've had stuff done to us.  From now on, if anyone tries to
     // document.open() us, they get a new inner window.
     SetIsInitialDocument(false);
 
     nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
     if (oldScope && newScope != oldScope) {
       nsIXPConnect *xpc = nsContentUtils::XPConnect();
       rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope->GetGlobalJSObject(),
                                              newScope->GetGlobalJSObject(),
                                              static_cast<nsINode*>(this));
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (rv.Failed()) {
+        return nullptr;
+      }
       rv = xpc->RescueOrphansInScope(cx, oldScope->GetGlobalJSObject());
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (rv.Failed()) {
+        return nullptr;
+      }
     }
   }
 
   // Call Reset(), this will now do the full reset
   Reset(channel, group);
   if (baseURI) {
     mDocumentBaseURI = baseURI;
   }
 
   // Store the security info of the caller now that we're done
   // resetting the document.
   mSecurityInfo = securityInfo;
 
   mParserAborted = false;
   mParser = nsHtml5Module::NewHtml5Parser();
   nsHtml5Module::Initialize(mParser, this, uri, shell, channel);
-  rv = NS_OK;
 
   // This will be propagated to the parser when someone actually calls write()
   SetContentTypeInternal(contentType);
 
   // Prepare the docshell and the document viewer for the impending
   // out of band document.write()
   shell->PrepareForNewContentModel();
 
   // Now check whether we were opened with a "replace" argument.  If
   // so, we need to tell the docshell to not create a new history
   // entry for this load. Otherwise, make sure that we're doing a normal load,
   // not whatever type of load was previously done on this docshell.
-  shell->SetLoadType(
-    (aOptionalArgCount > 1 && aReplaceOrName.EqualsLiteral("replace"))
-    ? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
+  shell->SetLoadType(aReplace.LowerCaseEqualsLiteral("replace") ?
+                       LOAD_NORMAL_REPLACE : LOAD_NORMAL);
 
   nsCOMPtr<nsIContentViewer> cv;
   shell->GetContentViewer(getter_AddRefs(cv));
   if (cv) {
     cv->LoadStart(static_cast<nsIHTMLDocument *>(this));
   }
 
   // Add a wyciwyg channel request into the document load group
@@ -1579,45 +1700,55 @@ nsHTMLDocument::Open(const nsAString& aC
 
   // After changing everything around, make sure that the principal on the
   // document's compartment exactly matches NodePrincipal().
   DebugOnly<JSObject*> wrapper = GetWrapperPreserveColor();
   MOZ_ASSERT_IF(wrapper,
                 JS_GetCompartmentPrincipals(js::GetObjectCompartment(wrapper)) ==
                 nsJSPrincipals::get(NodePrincipal()));
 
-  NS_ENSURE_SUCCESS(rv, rv);
-  return CallQueryInterface(this, aReturn);
+  return kungFuDeathGrip.forget();
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Clear()
 {
   // This method has been deprecated
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Close()
 {
+  ErrorResult rv;
+  Close(rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::Close(ErrorResult& rv)
+{
   if (!IsHTML()) {
     // No calling document.close() on XHTML!
 
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+    rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
   }
 
   if (!mParser || !mParser->IsScriptCreated()) {
-    return NS_OK;
+    return;
   }
 
   ++mWriteLevel;
-  nsresult rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+  rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
     EmptyString(), nullptr, GetContentTypeInternal(), true);
   --mWriteLevel;
 
+  // Even if that Parse() call failed, do the rest of this method
+
   // XXX Make sure that all the document.written content is
   // reflowed.  We should remove this call once we change
   // nsHTMLDocument::OpenCommon() so that it completely destroys the
   // earlier document's content and frame hierarchy.  Right now, it
   // re-uses the earlier document's root content object and
   // corresponding frame objects.  These re-used frame objects think
   // that they have already been reflowed, so they drop initial
   // reflows.  For certain cases of document.written content, like a
@@ -1643,17 +1774,37 @@ nsHTMLDocument::Close()
   // Removing the wyciwygChannel here is wrong when document.close() is
   // called from within the document itself. However, legacy requires the
   // channel to be removed here. Otherwise, the load event never fires.
   NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::Close(): Trying to remove "
                "nonexistent wyciwyg channel!");
   RemoveWyciwygChannel();
   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Close(): "
                "nsIWyciwygChannel could not be removed!");
-  return rv;
+}
+
+void
+nsHTMLDocument::WriteCommon(JSContext *cx,
+                            const Sequence<nsString>& aText,
+                            bool aNewlineTerminate,
+                            mozilla::ErrorResult& rv)
+{
+  // Fast path the common case
+  if (aText.Length() == 1) {
+    rv = WriteCommon(cx, aText[0], aNewlineTerminate);
+  } else {
+    // XXXbz it would be nice if we could pass all the strings to the parser
+    // without having to do all this copying and then ask it to start
+    // parsing....
+    nsString text;
+    for (uint32_t i = 0; i < aText.Length(); ++i) {
+      text.Append(aText[i]);
+    }
+    rv = WriteCommon(cx, text, aNewlineTerminate);
+  }
 }
 
 nsresult
 nsHTMLDocument::WriteCommon(JSContext *cx,
                             const nsAString& aText,
                             bool aNewlineTerminate)
 {
   mTooDeepWriteRecursion =
@@ -1751,22 +1902,36 @@ nsHTMLDocument::WriteCommon(JSContext *c
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Write(const nsAString& aText, JSContext *cx)
 {
   return WriteCommon(cx, aText, false);
 }
 
+void
+nsHTMLDocument::Write(JSContext* cx, const Sequence<nsString>& aText,
+                      ErrorResult& rv)
+{
+  WriteCommon(cx, aText, false, rv);
+}
+
 NS_IMETHODIMP
 nsHTMLDocument::Writeln(const nsAString& aText, JSContext *cx)
 {
   return WriteCommon(cx, aText, true);
 }
 
+void
+nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
+                        ErrorResult& rv)
+{
+  WriteCommon(cx, aText, true, rv);
+}
+
 bool
 nsHTMLDocument::MatchNameAttribute(nsIContent* aContent, int32_t aNamespaceID,
                                    nsIAtom* aAtom, void* aData)
 {
   NS_PRECONDITION(aContent, "Must have content node to work with!");
   nsString* elementName = static_cast<nsString*>(aData);
   return
     aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
@@ -1780,22 +1945,17 @@ nsHTMLDocument::UseExistingNameString(ns
 {
   return const_cast<nsString*>(aName);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
                                   nsIDOMNodeList** aReturn)
 {
-  nsRefPtr<nsContentList> list = GetElementsByName(aElementName);
-  NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
-
-  // Transfer ownership
-  list.forget(aReturn);
-
+  *aReturn = GetElementsByName(aElementName).get();
   return NS_OK;
 }
 
 static bool MatchItems(nsIContent* aContent, int32_t aNameSpaceID, 
                        nsIAtom* aAtom, void* aData)
 {
   if (!(aContent->IsElement() && aContent->AsElement()->IsHTML())) {
     return false;
@@ -1858,24 +2018,26 @@ static void* CreateTokens(nsINode* aRoot
     }
   }
   return tokens;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetItems(const nsAString& types, nsIDOMNodeList** aReturn)
 {
-  nsRefPtr<nsContentList> elements = 
-    NS_GetFuncStringNodeList(this, MatchItems, DestroyTokens, CreateTokens,
-                             types);
-  NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY);
-  elements.forget(aReturn);
+  *aReturn = GetItems(types).get();
   return NS_OK;
 }
 
+already_AddRefed<nsINodeList>
+nsHTMLDocument::GetItems(const nsAString& aTypeNames)
+{
+  return NS_GetFuncStringNodeList(this, MatchItems, DestroyTokens, CreateTokens,
+                                  aTypeNames);
+}
 
 void
 nsHTMLDocument::AddedForm()
 {
   ++mNumForms;
 }
 
 void
@@ -2009,39 +2171,54 @@ nsHTMLDocument::SetFgColor(const nsAStri
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsHTMLDocument::GetEmbeds(nsIDOMHTMLCollection** aEmbeds)
 {
+  NS_ADDREF(*aEmbeds = Embeds());
+  return NS_OK;
+}
+
+nsIHTMLCollection*
+nsHTMLDocument::Embeds()
+{
   if (!mEmbeds) {
     mEmbeds = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::embed, nsGkAtoms::embed);
   }
-
-  *aEmbeds = mEmbeds;
-  NS_ADDREF(*aEmbeds);
-
-  return NS_OK;
+  return mEmbeds;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetSelection(nsISelection** aReturn)
 {
+  ErrorResult rv;
+  *aReturn = GetSelection(rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsISelection>
+nsHTMLDocument::GetSelection(ErrorResult& rv)
+{
   nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());
   nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(window);
-  NS_ENSURE_TRUE(pwin, NS_OK);
+  if (!pwin) {
+    return nullptr;
+  }
   NS_ASSERTION(pwin->IsInnerWindow(), "Should have inner window here!");
-  NS_ENSURE_TRUE(pwin->GetOuterWindow() &&
-                 pwin->GetOuterWindow()->GetCurrentInnerWindow() == pwin,
-                 NS_OK);
-
-  return window->GetSelection(aReturn);
-  
+  if (!pwin->GetOuterWindow() ||
+      pwin->GetOuterWindow()->GetCurrentInnerWindow() != pwin) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsISelection> sel;
+  rv = window->GetSelection(getter_AddRefs(sel));
+  return sel.forget();
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::CaptureEvents(int32_t aEventFlags)
 {
   ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
   return NS_OK;
 }
@@ -2064,16 +2241,22 @@ nsHTMLDocument::RouteEvent(nsIDOMEvent* 
 NS_IMETHODIMP
 nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins)
 {
   *aPlugins = nullptr;
 
   return GetEmbeds(aPlugins);
 }
 
+nsIHTMLCollection*
+nsHTMLDocument::Plugins()
+{
+  return Embeds();
+}
+
 nsresult
 nsHTMLDocument::ResolveName(const nsAString& aName,
                             nsIContent *aForm,
                             nsISupports **aResult,
                             nsWrapperCache **aCache)
 {
   *aResult = nullptr;
   *aCache = nullptr;
@@ -2163,21 +2346,17 @@ nsHTMLDocument::ResolveName(const nsAStr
 
 //----------------------------
 
 // forms related stuff
 
 NS_IMETHODIMP
 nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms)
 {
-  nsContentList *forms = nsHTMLDocument::GetForms();
-  if (!forms)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(*aForms = forms);
+  NS_ADDREF(*aForms = nsHTMLDocument::GetForms());
   return NS_OK;
 }
 
 nsContentList*
 nsHTMLDocument::GetForms()
 {
   if (!mForms) {
     mForms = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::form, nsGkAtoms::form);
@@ -2792,40 +2971,51 @@ nsHTMLDocument::EditingStateChanged()
   editor->SyncRealTimeSpell();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetDesignMode(const nsAString & aDesignMode)
 {
-  nsresult rv = NS_OK;
-
+  ErrorResult rv;
+  SetDesignMode(aDesignMode, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode, ErrorResult& rv)
+{
   if (!nsContentUtils::IsCallerChrome()) {
     nsCOMPtr<nsIPrincipal> subject;
     nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
     rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return;
+    }
     if (subject) {
       bool subsumes;
       rv = subject->Subsumes(NodePrincipal(), &subsumes);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      NS_ENSURE_TRUE(subsumes, NS_ERROR_DOM_PROP_ACCESS_DENIED);
+      if (rv.Failed()) {
+        return;
+      }
+
+      if (!subsumes) {
+        rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
+        return;
+      }
     }
   }
 
   bool editableMode = HasFlag(NODE_IS_EDITABLE);
   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
     SetEditableFlag(!editableMode);
 
-    return EditingStateChanged();
+    rv = EditingStateChanged();
   }
-
-  return NS_OK;
 }
 
 nsresult
 nsHTMLDocument::GetMidasCommandManager(nsICommandManager** aCmdMgr)
 {
   // initialize return value
   NS_ENSURE_ARG_POINTER(aCmdMgr);
 
@@ -3128,316 +3318,417 @@ nsHTMLDocument::DoClipboardSecurityCheck
 /* boolean execCommand(in DOMString commandID, in boolean doShowUI,
                                                in DOMString value); */
 NS_IMETHODIMP
 nsHTMLDocument::ExecCommand(const nsAString& commandID,
                             bool doShowUI,
                             const nsAString& value,
                             bool* _retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-
+  ErrorResult rv;
+  *_retval = ExecCommand(commandID, doShowUI, value, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsHTMLDocument::ExecCommand(const nsAString& commandID,
+                            bool doShowUI,
+                            const nsAString& value,
+                            ErrorResult& rv)
+{
   //  for optional parameters see dom/src/base/nsHistory.cpp: HistoryImpl::Go()
   //  this might add some ugly JS dependencies?
 
-  *_retval = false;
-
   nsAutoCString cmdToDispatch, paramStr;
   bool isBool, boolVal;
   if (!ConvertToMidasInternalCommand(commandID, value,
                                      cmdToDispatch, paramStr,
                                      isBool, boolVal)) {
-    // Return false
-    return NS_OK;
+    return false;
   }
 
   // if editing is not on, bail
-  NS_ENSURE_TRUE(IsEditingOnAfterFlush(), NS_ERROR_FAILURE);
+  if (!IsEditingOnAfterFlush()) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   // if they are requesting UI from us, let's fail since we have no UI
   if (doShowUI) {
-    return NS_OK;
+    return false;
   }
 
   if (commandID.LowerCaseEqualsLiteral("gethtml")) {
-    return NS_ERROR_FAILURE;
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
   }
 
-  nsresult rv = NS_OK;
-
   if (commandID.LowerCaseEqualsLiteral("cut") ||
       commandID.LowerCaseEqualsLiteral("copy")) {
     rv = DoClipboardSecurityCheck(false);
   } else if (commandID.LowerCaseEqualsLiteral("paste")) {
     rv = DoClipboardSecurityCheck(true);
   }
 
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return false;
+  }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  NS_ENSURE_TRUE(cmdMgr, NS_ERROR_FAILURE);
+  if (!cmdMgr) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   nsIDOMWindow* window = GetWindow();
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  if (!window) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   if ((cmdToDispatch.EqualsLiteral("cmd_fontSize") ||
        cmdToDispatch.EqualsLiteral("cmd_insertImageNoUI") ||
        cmdToDispatch.EqualsLiteral("cmd_insertLinkNoUI") ||
        cmdToDispatch.EqualsLiteral("cmd_paragraphState")) &&
       paramStr.IsEmpty()) {
     // Invalid value, return false
-    return NS_OK;
+    return false;
   }
 
   // Return false for disabled commands (bug 760052)
   bool enabled = false;
   cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &enabled);
   if (!enabled) {
-    return NS_OK;
+    return false;
   }
 
   if (!isBool && paramStr.IsEmpty()) {
     rv = cmdMgr->DoCommand(cmdToDispatch.get(), nullptr, window);
   } else {
     // we have a command that requires a parameter, create params
     nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
-                                            NS_COMMAND_PARAMS_CONTRACTID, &rv);
-    NS_ENSURE_TRUE(cmdParams, NS_ERROR_OUT_OF_MEMORY);
+                                            NS_COMMAND_PARAMS_CONTRACTID);
+    if (!cmdParams) {
+      rv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return false;
+    }
 
     if (isBool) {
       rv = cmdParams->SetBooleanValue("state_attribute", boolVal);
     } else if (cmdToDispatch.EqualsLiteral("cmd_fontFace")) {
       rv = cmdParams->SetStringValue("state_attribute", value);
     } else if (cmdToDispatch.EqualsLiteral("cmd_insertHTML") ||
                cmdToDispatch.EqualsLiteral("cmd_insertText")) {
       rv = cmdParams->SetStringValue("state_data", value);
     } else {
       rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
     }
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return false;
+    }
     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
   }
 
-  *_retval = NS_SUCCEEDED(rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
+  return !rv.Failed();
 }
 
 /* boolean queryCommandEnabled(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandEnabled(const nsAString& commandID,
                                     bool* _retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = false;
-
+  ErrorResult rv;
+  *_retval = QueryCommandEnabled(commandID, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsHTMLDocument::QueryCommandEnabled(const nsAString& commandID, ErrorResult& rv)
+{
   nsAutoCString cmdToDispatch;
   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
-    // Return false
-    return NS_OK;
+    return false;
   }
 
   // if editing is not on, bail
-  NS_ENSURE_TRUE(IsEditingOnAfterFlush(), NS_ERROR_FAILURE);
+  if (!IsEditingOnAfterFlush()) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  NS_ENSURE_TRUE(cmdMgr, NS_ERROR_FAILURE);
+  if (!cmdMgr) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   nsIDOMWindow* window = GetWindow();
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-  return cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, _retval);
+  if (!window) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
+
+  bool retval;
+  rv = cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &retval);
+  return retval;
 }
 
 /* boolean queryCommandIndeterm (in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
                                      bool *_retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = false;
-
+  ErrorResult rv;
+  *_retval = QueryCommandIndeterm(commandID, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsHTMLDocument::QueryCommandIndeterm(const nsAString& commandID, ErrorResult& rv)
+{
   nsAutoCString cmdToDispatch;
   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
-    // Return false
-    return NS_OK;
+    return false;
   }
 
   // if editing is not on, bail
-  NS_ENSURE_TRUE(IsEditingOnAfterFlush(), NS_ERROR_FAILURE);
+  if (!IsEditingOnAfterFlush()) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  NS_ENSURE_TRUE(cmdMgr, NS_ERROR_FAILURE);
+  if (!cmdMgr) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   nsIDOMWindow* window = GetWindow();
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-  nsresult rv;
+  if (!window) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
+
+  nsresult res;
   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
-                                           NS_COMMAND_PARAMS_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+                                           NS_COMMAND_PARAMS_CONTRACTID, &res);
+  if (NS_FAILED(res)) {
+    rv.Throw(res);
+    return false;
+  }
 
   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return false;
+  }
 
   // If command does not have a state_mixed value, this call fails and sets
-  // *_retval to false.  This is fine -- we want to return false in that case
-  // anyway (bug 738385), so we just return NS_OK regardless.
-  cmdParams->GetBooleanValue("state_mixed", _retval);
-  return NS_OK;
+  // retval to false.  This is fine -- we want to return false in that case
+  // anyway (bug 738385), so we just don't throw regardless.
+  bool retval = false;
+  cmdParams->GetBooleanValue("state_mixed", &retval);
+  return retval;
 }
 
 /* boolean queryCommandState(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = false;
-
+  ErrorResult rv;
+  *_retval = QueryCommandState(commandID, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsHTMLDocument::QueryCommandState(const nsAString& commandID, ErrorResult& rv)
+{
   nsAutoCString cmdToDispatch, paramToCheck;
   bool dummy, dummy2;
   if (!ConvertToMidasInternalCommand(commandID, commandID,
                                      cmdToDispatch, paramToCheck,
                                      dummy, dummy2)) {
-    // Return false
-    return NS_OK;
+    return false;
   }
 
   // if editing is not on, bail
-  NS_ENSURE_TRUE(IsEditingOnAfterFlush(), NS_ERROR_FAILURE);
+  if (!IsEditingOnAfterFlush()) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  NS_ENSURE_TRUE(cmdMgr, NS_ERROR_FAILURE);
+  if (!cmdMgr) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   nsIDOMWindow* window = GetWindow();
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  if (!window) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
   if (commandID.LowerCaseEqualsLiteral("usecss")) {
     // Per spec, state is supported for styleWithCSS but not useCSS, so we just
     // return false always.
-    *_retval = false;
-    return NS_OK;
+    return false;
   }
 
-  nsresult rv;
   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
-                                           NS_COMMAND_PARAMS_CONTRACTID, &rv);
-  NS_ENSURE_TRUE(cmdParams, NS_ERROR_OUT_OF_MEMORY);
+                                           NS_COMMAND_PARAMS_CONTRACTID);
+  if (!cmdParams) {
+    rv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return false;
+  }
 
   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return false;
+  }
 
   // handle alignment as a special case (possibly other commands too?)
   // Alignment is special because the external api is individual
   // commands but internally we use cmd_align with different
   // parameters.  When getting the state of this command, we need to
   // return the boolean for this particular alignment rather than the
   // string of 'which alignment is this?'
   if (cmdToDispatch.EqualsLiteral("cmd_align")) {
     char * actualAlignmentType = nullptr;
     rv = cmdParams->GetCStringValue("state_attribute", &actualAlignmentType);
-    if (NS_SUCCEEDED(rv) && actualAlignmentType && actualAlignmentType[0]) {
-      *_retval = paramToCheck.Equals(actualAlignmentType);
+    bool retval = false;
+    if (!rv.Failed() && actualAlignmentType && actualAlignmentType[0]) {
+      retval = paramToCheck.Equals(actualAlignmentType);
     }
     if (actualAlignmentType) {
       nsMemory::Free(actualAlignmentType);
     }
-    NS_ENSURE_SUCCESS(rv, rv);
-    return NS_OK;
+    return retval;
   }
 
   // If command does not have a state_all value, this call fails and sets
-  // *_retval to false.  This is fine -- we want to return false in that case
-  // anyway (bug 738385), so we just return NS_OK regardless.
-  cmdParams->GetBooleanValue("state_all", _retval);
-  return NS_OK;
+  // retval to false.  This is fine -- we want to return false in that case
+  // anyway (bug 738385), so we just succeed and return false regardless.
+  bool retval = false;
+  cmdParams->GetBooleanValue("state_all", &retval);
+  return retval;
 }
 
 /* boolean queryCommandSupported(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandSupported(const nsAString & commandID,
                                       bool *_retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-
+  *_retval = QueryCommandSupported(commandID);
+  return NS_OK;
+}
+
+bool
+nsHTMLDocument::QueryCommandSupported(const nsAString& commandID)
+{
   // commandID is supported if it can be converted to a Midas command
   nsAutoCString cmdToDispatch;
-  *_retval = ConvertToMidasInternalCommand(commandID, cmdToDispatch);
-
-  return NS_OK;
+  return ConvertToMidasInternalCommand(commandID, cmdToDispatch);
 }
 
 /* DOMString queryCommandValue(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
                                   nsAString &_retval)
 {
-  _retval.SetLength(0);
+  ErrorResult rv;
+  QueryCommandValue(commandID, _retval, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsHTMLDocument::QueryCommandValue(const nsAString& commandID,
+                                  nsAString& aValue,
+                                  ErrorResult& rv)
+{
+  aValue.Truncate();
 
   nsAutoCString cmdToDispatch, paramStr;
   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
     // Return empty string
-    return NS_OK;
+    return;
   }
 
   // if editing is not on, bail
-  NS_ENSURE_TRUE(IsEditingOnAfterFlush(), NS_ERROR_FAILURE);
+  if (!IsEditingOnAfterFlush()) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  NS_ENSURE_TRUE(cmdMgr, NS_ERROR_FAILURE);
+  if (!cmdMgr) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   nsIDOMWindow* window = GetWindow();
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  if (!window) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   // create params
-  nsresult rv;
   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
-                                           NS_COMMAND_PARAMS_CONTRACTID, &rv);
-  NS_ENSURE_TRUE(cmdParams, NS_ERROR_OUT_OF_MEMORY);
+                                           NS_COMMAND_PARAMS_CONTRACTID);
+  if (!cmdParams) {
+    rv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return;
+  }
 
   // this is a special command since we are calling DoCommand rather than
   // GetCommandState like the other commands
   if (cmdToDispatch.EqualsLiteral("cmd_getContents")) {
     rv = cmdParams->SetBooleanValue("selection_only", true);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return;
+    }
     rv = cmdParams->SetCStringValue("format", "text/html");
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv.Failed()) {
+      return;
+    }
     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = cmdParams->GetStringValue("result", _retval);
-    NS_ENSURE_SUCCESS(rv, rv);
-    return NS_OK;
+    if (rv.Failed()) {
+      return;
+    }
+    rv = cmdParams->GetStringValue("result", aValue);
+    return;
   }
 
   rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return;
+  }
 
   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (rv.Failed()) {
+    return;
+  }
 
   // If command does not have a state_attribute value, this call fails, and
-  // _retval will wind up being the empty string.  This is fine -- we want to
+  // aValue will wind up being the empty string.  This is fine -- we want to
   // return "" in that case anyway (bug 738385), so we just return NS_OK
   // regardless.
   nsXPIDLCString cStringResult;
   cmdParams->GetCStringValue("state_attribute",
                              getter_Copies(cStringResult));
-  CopyUTF8toUTF16(cStringResult, _retval);
-
-  return NS_OK;
+  CopyUTF8toUTF16(cStringResult, aValue);
 }
 
 nsresult
 nsHTMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -104,24 +104,16 @@ public:
    * Returns the result of document.all[aID] which can either be a node
    * or a nodelist depending on if there are multiple nodes with the same
    * id.
    */
   nsISupports *GetDocumentAllResult(const nsAString& aID,
                                     nsWrapperCache **aCache,
                                     nsresult *aResult);
 
-  Element *GetBody();
-  Element *GetHead() { return GetHeadElement(); }
-  already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
-  {
-    return NS_GetFuncStringNodeList(this, MatchNameAttribute, nullptr,
-                                    UseExistingNameString, aName);
-  }
-
   virtual nsresult ResolveName(const nsAString& aName,
                                nsIContent *aForm,
                                nsISupports **aResult,
                                nsWrapperCache **aCache);
 
   virtual void AddedForm();
   virtual void RemovedForm();
   virtual int32_t GetNumFormsSynchronous();
@@ -176,16 +168,86 @@ public:
     return nsDocument::GetElementById(aElementId);
   }
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
   // DocSizeOfIncludingThis is inherited from nsIDocument.
 
+  // WebIDL API
+  void GetDomain(nsAString& aDomain, mozilla::ErrorResult& rv);
+  void SetDomain(const nsAString& aDomain, mozilla::ErrorResult& rv);
+  void GetCookie(nsAString& aCookie, mozilla::ErrorResult& rv);
+  void SetCookie(const nsAString& aCookie, mozilla::ErrorResult& rv);
+  nsGenericHTMLElement *GetBody();
+  void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
+  Element *GetHead() { return GetHeadElement(); }
+  nsIHTMLCollection* Images();
+  nsIHTMLCollection* Embeds();
+  nsIHTMLCollection* Plugins();
+  nsIHTMLCollection* Links();
+  nsIHTMLCollection* Forms()
+  {
+    return nsHTMLDocument::GetForms();
+  }
+  nsIHTMLCollection* Scripts();
+  already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
+  {
+    return NS_GetFuncStringNodeList(this, MatchNameAttribute, nullptr,
+                                    UseExistingNameString, aName);
+  }
+  already_AddRefed<nsINodeList> GetItems(const nsAString& aTypeNames);
+  already_AddRefed<nsIDocument> Open(JSContext* cx,
+                                     const nsAString& aType,
+                                     const nsAString& aReplace,
+                                     mozilla::ErrorResult& rv);
+  already_AddRefed<nsIDOMWindow> Open(JSContext* cx,
+                                      const nsAString& aURL,
+                                      const nsAString& aName,
+                                      const nsAString& aFeatures,
+                                      bool aReplace,
+                                      mozilla::ErrorResult& rv);
+  void Close(mozilla::ErrorResult& rv);
+  void Write(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
+             mozilla::ErrorResult& rv);
+  void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
+               mozilla::ErrorResult& rv);
+  // The XPCOM GetDesignMode() works OK for us, since it never throws.
+  void SetDesignMode(const nsAString& aDesignMode, mozilla::ErrorResult& rv);
+  bool ExecCommand(const nsAString& aCommandID, bool aDoShowUI,
+                   const nsAString& aValue, mozilla::ErrorResult& rv);
+  bool QueryCommandEnabled(const nsAString& aCommandID,
+                           mozilla::ErrorResult& rv);
+  bool QueryCommandIndeterm(const nsAString& aCommandID,
+                            mozilla::ErrorResult& rv);
+  bool QueryCommandState(const nsAString& aCommandID, mozilla::ErrorResult& rv);
+  bool QueryCommandSupported(const nsAString& aCommandID);
+  void QueryCommandValue(const nsAString& aCommandID, nsAString& aValue,
+                         mozilla::ErrorResult& rv);
+  // The XPCOM Get/SetFgColor work OK for us, since they never throw.
+  // The XPCOM Get/SetLinkColor work OK for us, since they never throw.
+  // The XPCOM Get/SetVLinkColor work OK for us, since they never throw.
+  // The XPCOM Get/SetALinkColor work OK for us, since they never throw.
+  // The XPCOM Get/SetBgColor work OK for us, since they never throw.
+  nsIHTMLCollection* Anchors();
+  nsIHTMLCollection* Applets();
+  void Clear() const
+  {
+    // Deprecated
+  }
+  already_AddRefed<nsISelection> GetSelection(mozilla::ErrorResult& rv);
+  // The XPCOM CaptureEvents works fine for us.
+  // The XPCOM ReleaseEvents works fine for us.
+  // The XPCOM RouteEvent works fine for us.
+  // We're picking up GetLocation from Document
+  already_AddRefed<nsIDOMLocation> GetLocation() const {
+    return nsIDocument::GetLocation();
+  }
+
 protected:
   nsresult GetBodySize(int32_t* aWidth,
                        int32_t* aHeight);
 
   nsIContent *MatchId(nsIContent *aContent, const nsAString& aId);
 
   static bool MatchLinks(nsIContent *aContent, int32_t aNamespaceID,
                            nsIAtom* aAtom, void* aData);
@@ -196,33 +258,38 @@ protected:
   static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
 
   static void DocumentWriteTerminationFunc(nsISupports *aRef);
 
   void GetDomainURI(nsIURI **uri);
 
   nsresult WriteCommon(JSContext *cx, const nsAString& aText,
                        bool aNewlineTerminate);
+  // A version of WriteCommon used by WebIDL bindings
+  void WriteCommon(JSContext *cx,
+                   const mozilla::dom::Sequence<nsString>& aText,
+                   bool aNewlineTerminate,
+                   mozilla::ErrorResult& rv);
 
   nsresult CreateAndAddWyciwygChannel(void);
   nsresult RemoveWyciwygChannel(void);
 
   /**
    * Like IsEditingOn(), but will flush as needed first.
    */
   bool IsEditingOnAfterFlush();
 
   void *GenerateParserKey(void);
 
-  nsCOMPtr<nsIDOMHTMLCollection> mImages;
-  nsCOMPtr<nsIDOMHTMLCollection> mApplets;
-  nsCOMPtr<nsIDOMHTMLCollection> mEmbeds;
-  nsCOMPtr<nsIDOMHTMLCollection> mLinks;
-  nsCOMPtr<nsIDOMHTMLCollection> mAnchors;
-  nsCOMPtr<nsIDOMHTMLCollection> mScripts;
+  nsRefPtr<nsContentList> mImages;
+  nsRefPtr<nsContentList> mApplets;
+  nsRefPtr<nsContentList> mEmbeds;
+  nsRefPtr<nsContentList> mLinks;
+  nsRefPtr<nsContentList> mAnchors;
+  nsRefPtr<nsContentList> mScripts;
   nsRefPtr<nsContentList> mForms;
   nsRefPtr<nsContentList> mFormControls;
 
   /** # of forms in the document, synchronously set */
   int32_t mNumForms;
 
   static uint32_t gWyciwygSessionCnt;
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -291,16 +291,23 @@ DOMInterfaces = {
 },
 
 'HTMLDataListElement': {
     'resultNotAddRefed': [
         'options'
     ]
 },
 
+'HTMLDocument': {
+    'nativeType': 'nsHTMLDocument',
+    'resultNotAddRefed': [ 'body', 'head', 'images', 'embeds', 'plugins',
+                           'links', 'forms', 'scripts', 'anchors', 'applets' ],
+    'implicitJSContext': [ 'open', 'write', 'writeln' ]
+},
+
 'HTMLElement': {
     'nativeType': 'nsGenericHTMLElement',
     'hasXPConnectImpls': True,
     'hasInstanceInterface': 'nsIDOMHTMLElement',
     'resultNotAddRefed': [
         'itemType', 'itemRef', 'itemProp', 'properties', 'contextMenu', 'style',
         'offsetParent'
     ]
@@ -992,28 +999,30 @@ addExternalIface('ClientRect')
 addExternalIface('Comment', nativeType='mozilla::dom::Comment')
 addExternalIface("Counter")
 addExternalIface('CSSRule')
 addExternalIface('DocumentType', headerFile="nsDOMDocumentType.h")
 addExternalIface('DOMRequest')
 addExternalIface('DOMStringList')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
+addExternalIface('HTMLHeadElement', nativeType='mozilla::dom::Element')
 addExternalIface('LockedFile')
 addExternalIface('MediaStream')
 addExternalIface('NamedNodeMap')
 addExternalIface('NodeIterator')
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('ProcessingInstruction', nativeType='nsXMLProcessingInstruction')
 addExternalIface('Range', nativeType='nsRange')
 addExternalIface("Rect")
+addExternalIface('Selection', nativeType='nsISelection')
 addExternalIface('StyleSheetList')
 addExternalIface('SVGAnimatedString')
 addExternalIface('SVGLength')
 addExternalIface('SVGNumber')
 addExternalIface('SVGSVGElement', nativeType='nsSVGSVGElement')
 addExternalIface('Text', nativeType='nsTextNode')
 addExternalIface('TextMetrics', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('TreeWalker')
new file mode 100644
--- /dev/null
+++ b/dom/webidl/HTMLDocument.webidl
@@ -0,0 +1,77 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+interface HTMLHeadElement;
+interface Selection;
+
+interface HTMLDocument : Document {
+           [Throws]
+           attribute DOMString? domain;
+           [Throws]
+           attribute DOMString cookie;
+  // DOM tree accessors
+  //(Not proxy yet)getter object (DOMString name);
+           [SetterThrows]
+           attribute HTMLElement? body;
+  readonly attribute HTMLHeadElement? head;
+  readonly attribute HTMLCollection images;
+  readonly attribute HTMLCollection embeds;
+  readonly attribute HTMLCollection plugins;
+  readonly attribute HTMLCollection links;
+  readonly attribute HTMLCollection forms;
+  readonly attribute HTMLCollection scripts;
+  NodeList getElementsByName(DOMString elementName);
+  NodeList getItems(optional DOMString typeNames = ""); // microdata
+
+  // dynamic markup insertion
+  [Throws]
+  Document open(optional DOMString type = "text/html", optional DOMString replace = "");
+  [Throws]
+  WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
+  [Throws]
+  void close();
+  [Throws]
+  void write(DOMString... text);
+  [Throws]
+  void writeln(DOMString... text);
+
+           [SetterThrows]
+           attribute DOMString designMode;
+  [Throws]
+  boolean execCommand(DOMString commandId, optional boolean showUI = false,
+                      optional DOMString value = "");
+  [Throws]
+  boolean queryCommandEnabled(DOMString commandId);
+  [Throws]
+  boolean queryCommandIndeterm(DOMString commandId);
+  [Throws]
+  boolean queryCommandState(DOMString commandId);
+  boolean queryCommandSupported(DOMString commandId);
+  [Throws]
+  DOMString queryCommandValue(DOMString commandId);
+
+  [TreatNullAs=EmptyString] attribute DOMString fgColor;
+  [TreatNullAs=EmptyString] attribute DOMString linkColor;
+  [TreatNullAs=EmptyString] attribute DOMString vlinkColor;
+  [TreatNullAs=EmptyString] attribute DOMString alinkColor;
+  [TreatNullAs=EmptyString] attribute DOMString bgColor;
+
+  readonly attribute HTMLCollection anchors;
+  readonly attribute HTMLCollection applets;
+
+  void clear();
+
+  // https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
+  [Throws]
+  Selection getSelection();
+
+  // @deprecated These are old Netscape 4 methods. Do not use,
+  //             the implementation is no-op.
+  // XXXbz do we actually need these anymore?
+  void                      captureEvents(long eventFlags);
+  void                      releaseEvents(long eventFlags);
+  void                      routeEvent(Event evt);
+};