Bug 1494230 - replace #text-base binding by webidl control, r=smaug
authorAlexander Surkov <surkov.alexander@gmail.com>
Mon, 01 Oct 2018 11:37:39 +0800
changeset 438933 274e2637419e7fff7105b7060303f327b6df705a
parent 438932 948d251c50ee0c25f30bb032a089a9e83434f756
child 438934 4d0ca51d2c0ceb064db11e06782fb415b0ed2641
push id34747
push usernerli@mozilla.com
push dateMon, 01 Oct 2018 09:42:05 +0000
treeherdermozilla-central@cc0bf89a7eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1494230
milestone64.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 1494230 - replace #text-base binding by webidl control, r=smaug
devtools/client/canvasdebugger/test/browser_canvas-frontend-call-list.js
dom/bindings/BindingUtils.cpp
dom/chrome-webidl/XULTextElement.webidl
dom/chrome-webidl/moz.build
dom/tests/mochitest/chrome/chrome.ini
dom/tests/mochitest/chrome/test_elements_proto.xul
dom/tests/mochitest/general/test_interfaces.js
dom/xul/XULTextElement.cpp
dom/xul/XULTextElement.h
dom/xul/moz.build
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
toolkit/content/widgets/text.xml
toolkit/content/xul.css
--- a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-list.js
+++ b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-list.js
@@ -48,17 +48,17 @@ async function ifTestingSupported() {
 
     is($(".call-item-index", item.target).getAttribute("value"), index,
       "The item's gutter label has the correct text.");
 
     if (context) {
       is($(".call-item-context", item.target).getAttribute("value"), context,
         "The item's context label has the correct text.");
     } else {
-      is($(".call-item-context", item.target) + "", "[object XULElement]",
+      is($(".call-item-context", item.target) + "", "[object XULTextElement]",
         "The item's context label should not be available.");
     }
 
     is($(".call-item-name", item.target).getAttribute("value"), name,
       "The item's name label has the correct text.");
     is($(".call-item-args", item.target).getAttribute("value"), args,
       "The item's args label has the correct text.");
     is($(".call-item-location", item.target).getAttribute("value"), location,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -49,16 +49,17 @@
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/XULElementBinding.h"
 #include "mozilla/dom/XULFrameElementBinding.h"
 #include "mozilla/dom/XULMenuElementBinding.h"
 #include "mozilla/dom/XULPopupElementBinding.h"
+#include "mozilla/dom/XULTextElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ResolveSystemBinding.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/XrayExpandoClass.h"
 #include "mozilla/dom/XULScrollElementBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -3865,20 +3866,23 @@ HTMLConstructor(JSContext* aCx, unsigned
   // Steps 4 and 5 do some sanity checks on our callee.  We add to those a
   // determination of what sort of element we're planning to construct.
   // Technically, this should happen (implicitly) in step 8, but this
   // determination is side-effect-free, so it's OK.
   int32_t ns = definition->mNamespaceID;
 
   constructorGetterCallback cb = nullptr;
   if (ns == kNameSpaceID_XUL) {
-    if (definition->mLocalName == nsGkAtoms::menupopup ||
-        definition->mLocalName == nsGkAtoms::popup ||
-        definition->mLocalName == nsGkAtoms::panel ||
-        definition->mLocalName == nsGkAtoms::tooltip) {
+    if (definition->mLocalName == nsGkAtoms::description ||
+        definition->mLocalName == nsGkAtoms::label) {
+      cb = XULTextElement_Binding::GetConstructorObject;
+    } else if (definition->mLocalName == nsGkAtoms::menupopup ||
+               definition->mLocalName == nsGkAtoms::popup ||
+               definition->mLocalName == nsGkAtoms::panel ||
+               definition->mLocalName == nsGkAtoms::tooltip) {
       cb = XULPopupElement_Binding::GetConstructorObject;
     } else if (definition->mLocalName == nsGkAtoms::iframe ||
                 definition->mLocalName == nsGkAtoms::browser ||
                 definition->mLocalName == nsGkAtoms::editor) {
       cb = XULFrameElement_Binding::GetConstructorObject;
     } else if (definition->mLocalName == nsGkAtoms::menu ||
                definition->mLocalName == nsGkAtoms::menulist) {
       cb = XULMenuElement_Binding::GetConstructorObject;
new file mode 100644
--- /dev/null
+++ b/dom/chrome-webidl/XULTextElement.webidl
@@ -0,0 +1,12 @@
+
+/* -*- 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/.
+ */
+
+[HTMLConstructor, Func="IsChromeOrXBL"]
+interface XULTextElement : XULElement {
+  attribute boolean disabled;
+  attribute DOMString value;
+};
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -46,17 +46,18 @@ WEBIDL_FILES = [
     'MozStorageStatementRow.webidl',
     'PrecompiledScript.webidl',
     'PromiseDebugging.webidl',
     'StructuredCloneHolder.webidl',
     'WebExtensionContentScript.webidl',
     'WebExtensionPolicy.webidl',
     'XULFrameElement.webidl',
     'XULMenuElement.webidl',
-    'XULScrollElement.webidl'
+    'XULScrollElement.webidl',
+    'XULTextElement.webidl'
 ]
 
 if CONFIG['MOZ_PLACES']:
     WEBIDL_FILES += [
         'PlacesEvent.webidl',
         'PlacesObservers.webidl',
     ]
 
--- a/dom/tests/mochitest/chrome/chrome.ini
+++ b/dom/tests/mochitest/chrome/chrome.ini
@@ -49,16 +49,17 @@ tags = openwindow
 skip-if = os != 'mac'
 [test_bug1224790-2.xul]
 tags = openwindow
 skip-if = os != 'mac'
 [test_callback_wrapping.xul]
 [test_clonewrapper.xul]
 [test_cyclecollector.xul]
 [test_docshell_swap.xul]
+[test_elements_proto.xul]
 [test_focus.xul]
 skip-if = os == 'linux' && !debug # bug 1296622
 [test_focus_docnav.xul]
 [test_focus_switchbinding.xul]
 [test_focused_link_scroll.xul]
 [test_fullscreen.xul]
 tags = fullscreen
 # disabled on linux for timeouts--bug-867745
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_elements_proto.xul
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+
+<window title="Mozilla Bug 861493"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  </body>
+
+  <script type="application/javascript">
+  <![CDATA[
+    const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+    SimpleTest.waitForExplicitFinish();
+
+    addLoadEvent(() => {
+      is(Object.getPrototypeOf(document.createElementNS(XUL_NS, "label")),
+         XULTextElement.prototype,
+        `<label> should be of XULTextElement type`);
+
+      is(Object.getPrototypeOf(document.createElementNS(XUL_NS, "description")),
+         XULTextElement.prototype,
+        `<description> should be of XULTextElement type`);
+
+      SimpleTest.finish();
+    });
+  ]]>
+  </script>
+</window>
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -1258,16 +1258,18 @@ var interfaceNamesInGlobalScope =
     {name: "XULFrameElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULMenuElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULPopupElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULScrollElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "XULTextElement", insecureContext: true, xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
   {
new file mode 100644
--- /dev/null
+++ b/dom/xul/XULTextElement.cpp
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "nsCOMPtr.h"
+#include "nsIPresShell.h"
+#include "nsIContent.h"
+#include "nsPresContext.h"
+#include "nsBox.h"
+#include "nsIScrollableFrame.h"
+#include "mozilla/dom/XULTextElement.h"
+#include "mozilla/dom/XULTextElementBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+XULTextElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return XULTextElement_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/xul/XULTextElement.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef XULTextElement_h__
+#define XULTextElement_h__
+
+#include "nsXULElement.h"
+
+namespace mozilla {
+namespace dom {
+
+
+class XULTextElement final : public nsXULElement
+{
+public:
+  explicit XULTextElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+    : nsXULElement(std::move(aNodeInfo))
+  {
+  }
+
+  bool Disabled()
+  {
+    return GetXULBoolAttr(nsGkAtoms::disabled);
+  }
+  MOZ_CAN_RUN_SCRIPT void SetDisabled(bool aValue)
+  {
+    SetXULBoolAttr(nsGkAtoms::disabled, aValue);
+  }
+  void GetValue(DOMString& aValue) const
+  {
+    GetXULAttr(nsGkAtoms::value, aValue);
+  }
+  MOZ_CAN_RUN_SCRIPT void SetValue(const nsAString& aValue)
+  {
+    SetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue, true);
+  }
+
+protected:
+  virtual ~XULTextElement() {}
+  JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) final;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // XULTextElement_h
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -21,32 +21,34 @@ if CONFIG['MOZ_XUL']:
         'nsXULSortService.h',
     ]
 
     EXPORTS.mozilla.dom += [
         'XULFrameElement.h',
         'XULMenuElement.h',
         'XULPopupElement.h',
         'XULScrollElement.h',
+        'XULTextElement.h'
     ]
 
     UNIFIED_SOURCES += [
         'nsXULCommandDispatcher.cpp',
         'nsXULContentSink.cpp',
         'nsXULContentUtils.cpp',
         'nsXULElement.cpp',
         'nsXULPopupListener.cpp',
         'nsXULPrototypeCache.cpp',
         'nsXULPrototypeDocument.cpp',
         'nsXULSortService.cpp',
         'XULDocument.cpp',
         'XULFrameElement.cpp',
         'XULMenuElement.cpp',
         'XULPopupElement.cpp',
         'XULScrollElement.cpp',
+        'XULTextElement.cpp'
     ]
 
 XPIDL_SOURCES += [
     'nsIController.idl',
     'nsIControllers.idl',
 ]
 
 XPIDL_MODULE = 'xul'
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -141,16 +141,21 @@ nsXULElement* NS_NewBasicXULElement(alre
 {
     return new nsXULElement(std::move(aNodeInfo));
 }
 
  /* static */
 nsXULElement* nsXULElement::Construct(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
+  if (nodeInfo->Equals(nsGkAtoms::label) ||
+      nodeInfo->Equals(nsGkAtoms::description)) {
+    return new XULTextElement(nodeInfo.forget());
+  }
+
   if (nodeInfo->Equals(nsGkAtoms::menupopup) ||
       nodeInfo->Equals(nsGkAtoms::popup) ||
       nodeInfo->Equals(nsGkAtoms::panel) ||
       nodeInfo->Equals(nsGkAtoms::tooltip)) {
     return NS_NewXULPopupElement(nodeInfo.forget());
   }
 
   if (nodeInfo->Equals(nsGkAtoms::iframe) ||
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -414,16 +414,21 @@ public:
     {
         GetAttr(kNameSpaceID_None, aName, aResult);
     }
     void SetXULAttr(nsAtom* aName, const nsAString& aValue,
                     mozilla::ErrorResult& aError)
     {
         SetAttr(aName, aValue, aError);
     }
+    bool GetXULBoolAttr(nsAtom* aName) const
+    {
+        return AttrValueIs(kNameSpaceID_None, aName,
+                           NS_LITERAL_STRING("true"), eCaseMatters);
+    }
     void SetXULBoolAttr(nsAtom* aName, bool aValue)
     {
         if (aValue) {
             SetAttr(kNameSpaceID_None, aName, NS_LITERAL_STRING("true"), true);
         } else {
             UnsetAttr(kNameSpaceID_None, aName, true);
         }
     }
--- a/toolkit/content/widgets/text.xml
+++ b/toolkit/content/widgets/text.xml
@@ -4,29 +4,17 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 
 <bindings id="textBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:html="http://www.w3.org/1999/xhtml">
 
-  <!-- bound to <description>s -->
-  <binding id="text-base">
-    <implementation>
-      <property name="disabled" onset="if (val) this.setAttribute('disabled', 'true');
-                                       else this.removeAttribute('disabled');
-                                       return val;"
-                                onget="return this.getAttribute('disabled') == 'true';"/>
-      <property name="value" onget="return this.getAttribute('value');"
-                             onset="this.setAttribute('value', val); return val;"/>
-    </implementation>
-  </binding>
-
-  <binding id="text-label" extends="chrome://global/content/bindings/text.xml#text-base">
+  <binding id="text-label">
     <implementation>
       <property name="accessKey">
         <getter>
           <![CDATA[
             var accessKey = this.getAttribute("accesskey");
             return accessKey ? accessKey[0] : null;
           ]]>
         </getter>
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -95,20 +95,16 @@ page {
 /******** box *******/
 
 vbox {
   -moz-box-orient: vertical;
 }
 
 /********** label **********/
 
-description {
-  -moz-binding: url("chrome://global/content/bindings/text.xml#text-base");
-}
-
 label {
   -moz-binding: url("chrome://global/content/bindings/text.xml#text-label");
 }
 
 label.text-link, label[onclick] {
   -moz-binding: url("chrome://global/content/bindings/text.xml#text-link");
   -moz-user-focus: normal;
 }