Bug 629801 Implement HTML5 <time> element. r=smaug, peterv, hsivonen
authorDavid Humphrey (:humph) <david.humphrey@senecacollege.ca>
Fri, 22 Feb 2013 10:07:42 -0500
changeset 122727 76f5d877e6f6638cd061e703d27ce2d4e1e5ee23
parent 122726 62f3d4a4421a775a3870901db8b8a11179037759
child 122728 5f688e2b37dccad4022bede8f5fdd199a8c2db1e
push id24356
push usergszorc@mozilla.com
push dateSun, 24 Feb 2013 01:00:12 +0000
treeherdermozilla-central@195e706140d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, peterv, hsivonen
bugs629801
milestone22.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 629801 Implement HTML5 <time> element. r=smaug, peterv, hsivonen
content/html/content/src/HTMLTimeElement.cpp
content/html/content/src/HTMLTimeElement.h
content/html/content/src/Makefile.in
content/html/content/src/nsGenericHTMLElement.h
content/html/content/test/Makefile.in
content/html/content/test/test_bug389797.html
content/html/content/test/test_bug629801.html
dom/imptests/failures/html/old-tests/submission/Opera/microdata/test_001.html.json
dom/webidl/HTMLTimeElement.webidl
dom/webidl/WebIDL.mk
editor/libeditor/base/nsEditPropertyAtomList.h
editor/libeditor/html/nsHTMLEditUtils.cpp
parser/htmlparser/public/nsHTMLTagList.h
parser/htmlparser/src/nsElementTable.cpp
parser/htmlparser/src/nsHTMLTags.cpp
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLTimeElement.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; 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/. */
+
+#include "HTMLTimeElement.h"
+#include "mozilla/dom/HTMLTimeElementBinding.h"
+#include "nsContentUtils.h"
+#include "nsGenericHTMLElement.h"
+#include "nsVariant.h"
+#include "nsGkAtoms.h"
+
+NS_IMPL_NS_NEW_HTML_ELEMENT(Time)
+
+namespace mozilla {
+namespace dom {
+
+HTMLTimeElement::HTMLTimeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : nsGenericHTMLElement(aNodeInfo)
+{
+  SetIsDOMBinding();
+}
+
+HTMLTimeElement::~HTMLTimeElement()
+{
+}
+
+NS_IMPL_ADDREF_INHERITED(HTMLTimeElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLTimeElement, Element)
+
+NS_INTERFACE_TABLE_HEAD(HTMLTimeElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE0(HTMLTimeElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLTimeElement,
+                                               nsGenericHTMLElement)
+NS_HTML_CONTENT_INTERFACE_MAP_END
+
+NS_IMPL_ELEMENT_CLONE(HTMLTimeElement)
+
+JSObject*
+HTMLTimeElement::WrapNode(JSContext* cx, JSObject* scope, bool* triedToWrap)
+{
+  return HTMLTimeElementBinding::Wrap(cx, scope, this, triedToWrap);
+}
+
+void
+HTMLTimeElement::GetItemValueText(nsAString& text)
+{
+  if (HasAttr(kNameSpaceID_None, nsGkAtoms::datetime)) {
+    GetDateTime(text);
+  } else {
+    GetTextContentInternal(text);
+  }
+}
+
+void
+HTMLTimeElement::SetItemValueText(const nsAString& text)
+{
+  ErrorResult rv;
+  SetDateTime(text, rv);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLTimeElement.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; 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/. */
+
+#ifndef mozilla_dom_HTMLTimeElement_h
+#define mozilla_dom_HTMLTimeElement_h
+
+#include "nsIDOMHTMLElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsGkAtoms.h"
+
+namespace mozilla {
+namespace dom {
+
+class HTMLTimeElement MOZ_FINAL : public nsGenericHTMLElement,
+                                  public nsIDOMHTMLElement
+{
+public:
+  HTMLTimeElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLTimeElement();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
+
+  // HTMLTimeElement WebIDL
+  void GetDateTime(nsAString& aDateTime)
+  {
+    GetHTMLAttr(nsGkAtoms::datetime, aDateTime);
+  }
+
+  void SetDateTime(const nsAString& aDateTime, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aError);
+  }
+
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
+  virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
+                             bool* aTriedToWrap) MOZ_OVERRIDE;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLTimeElement_h
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -67,16 +67,17 @@ EXPORTS_mozilla/dom = \
 		HTMLStyleElement.h \
 		HTMLTableCaptionElement.h \
 		HTMLTableCellElement.h \
 		HTMLTableColElement.h \
 		HTMLTableElement.h \
 		HTMLTableRowElement.h \
 		HTMLTableSectionElement.h \
 		HTMLTextAreaElement.h \
+		HTMLTimeElement.h \
 		HTMLTitleElement.h \
 		HTMLUnknownElement.h \
 		UndoManager.h \
 		ValidityState.h \
 		$(NULL)
 
 CPPSRCS		= \
 		HTMLPropertiesCollection.cpp \
@@ -131,16 +132,17 @@ CPPSRCS		= \
 		HTMLStyleElement.cpp \
 		HTMLTableElement.cpp \
 		HTMLTableCaptionElement.cpp \
 		HTMLTableCellElement.cpp \
 		HTMLTableColElement.cpp \
 		HTMLTableRowElement.cpp \
 		HTMLTableSectionElement.cpp \
 		HTMLTextAreaElement.cpp \
+		HTMLTimeElement.cpp \
 		HTMLTitleElement.cpp \
 		HTMLUnknownElement.cpp \
 		ValidityState.cpp \
 		nsIConstraintValidation.cpp \
 		nsRadioVisitor.cpp \
 		nsDOMStringMap.cpp \
 		UndoManager.cpp \
 		$(NULL)
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -1957,16 +1957,17 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell
 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Table)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableRow)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableSection)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Tbody)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Time)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Title)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown)
 #if defined(MOZ_MEDIA)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Video)
 #endif
 
 inline nsISupports*
 ToSupports(nsGenericHTMLElement* aHTMLElement)
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -345,16 +345,17 @@ MOCHITEST_FILES = \
 		test_htmlcollection.html \
 		test_formelements.html \
 		test_rowscollection.html \
 		test_map_attributes_reflection.html \
 		test_meta_attributes_reflection.html \
 		test_mod_attributes_reflection.html \
 		test_mozaudiochannel.html \
 		test_style_attributes_reflection.html \
+		test_bug629801.html \
 		$(NULL)
 
 
 MOCHITEST_BROWSER_FILES = \
 		browser_bug649778.js \
 		file_bug649778.html \
 		file_bug649778.html^headers^ \
 		$(NULL)
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -208,16 +208,17 @@ HTML_TAG("sub", "");
 HTML_TAG("sup", "");
 HTML_TAG("table", "Table");
 HTML_TAG("tbody", "TableSection");
 HTML_TAG("td", "TableCell");
 HTML_TAG("textarea", "TextArea", [], [ "nsIDOMNSEditableElement" ]);
 HTML_TAG("tfoot", "TableSection");
 HTML_TAG("th", "TableCell");
 HTML_TAG("thead", "TableSection");
+HTML_TAG("time", "Time");
 HTML_TAG("title", "Title");
 HTML_TAG("tr", "TableRow");
 HTML_TAG("tt", "");
 HTML_TAG("u", "");
 HTML_TAG("ul", "UList");
 HTML_TAG("var", "");
 HTML_TAG("wbr", "");
 HTML_TAG("xmp", "");
@@ -249,36 +250,14 @@ for (var tag of allTags) {
 
   // Check that each node QIs to all the things we expect it to QI to
   for (var iface of interfaces[tag].concat(interfacesNonClassinfo[tag])) {
     is(iface in SpecialPowers.Ci, true,
        iface + " not in Components.interfaces");
     is(node instanceof SpecialPowers.Ci[iface], true,
        tagName(tag) + " does not QI to " + iface);
   }
-
-  // Now see what classinfo reports
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var nodeClassInfo = SpecialPowers.wrap(node).QueryInterface(SpecialPowers.Ci.nsIClassInfo);
-  var count = {};
-  var classInfoInterfaces =
-    nodeClassInfo.getInterfaces(count).
-    map(function(id) { return SpecialPowers.Components.interfacesByID[id].toString(); });
-
-  // Make sure that we know about all the things classinfo claims
-  for (var classInfoInterface of classInfoInterfaces) {
-    isnot(interfaces[tag].indexOf(classInfoInterface), -1,
-          "Should know about " + tagName(tag) + " implementing " +
-          classInfoInterface);
-  }
-
-  // And make sure classinfo claims all the things we know about
-  for (iface of interfaces[tag]) {
-    isnot(classInfoInterfaces.indexOf(iface), -1,
-          "Classinfo for " + tagName(tag) + " should claim to implement " +
-          iface);
-  }
 }
 </script>
 </pre>
 </body>
 </html>
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug629801.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=629801
+-->
+<head>
+  <title>Test for Bug 629801</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="reflect.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=629801">Mozilla Bug 629801</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<div itemscope>
+ This tests itemValue on time elements, first with no datetime attribute, then with no text content,
+ then with both.
+ <time id="t1" itemprop="a">May 10th 2009</time>
+ <time id="t2" itemprop="b" datetime="2009-05-10"></time>
+ <time id="t3" itemprop="c" datetime="2009-05-10">May 10th 2009</time>
+</div>
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 629801 **/
+
+var t1 = document.getElementById("t1"),
+    t2 = document.getElementById("t2"),
+    t3 = document.getElementById("t3"),
+    t4 = document.createElement("time");
+
+// .dateTime IDL
+is(t1.dateTime, "", "dateTime is properly set to empty string if datetime attributeis absent");
+is(t2.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and no text content");
+is(t3.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and text content");
+
+// .itemValue getter for <time>'s microdata
+var times = document.getItems()[0];
+is(times.properties["a"][0].itemValue, "May 10th 2009", "itemValue getter with no datetime uses text content");
+is(times.properties["b"][0].itemValue, "2009-05-10", "itemValue getter with no text content uses datetime");
+is(times.properties["c"][0].itemValue, "2009-05-10", "itemValue getter with datetime and text content uses datetime");
+
+// .itemValue setter uses datetime vs. text content
+times.properties["a"][0].itemValue = "2009-05-10";
+is(times.properties["a"][0].dateTime, "2009-05-10", "setting itemValue updates datetime");
+
+// dateTime reflects datetime attribute
+reflectString({
+  element: t4,
+  attribute: "dateTime"
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/imptests/failures/html/old-tests/submission/Opera/microdata/test_001.html.json
+++ b/dom/imptests/failures/html/old-tests/submission/Opera/microdata/test_001.html.json
@@ -1,5 +1,3 @@
 {
-  "itemValue must reflect the src attribute on track elements": true,
-  "itemValue must reflect the dateTime attribute of time elements with no datetime attribute": true,
-  "itemValue must reflect the datetime attribute of time elements with a datetime attribute": true
+  "itemValue must reflect the src attribute on track elements": true
 }
new file mode 100644
--- /dev/null
+++ b/dom/webidl/HTMLTimeElement.webidl
@@ -0,0 +1,13 @@
+/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-time-element
+ */
+
+interface HTMLTimeElement : HTMLElement {
+           [SetterThrows]
+           attribute DOMString dateTime;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -104,16 +104,17 @@ webidl_files = \
   HTMLStyleElement.webidl \
   HTMLTableCaptionElement.webidl \
   HTMLTableCellElement.webidl \
   HTMLTableColElement.webidl \
   HTMLTableElement.webidl \
   HTMLTableRowElement.webidl \
   HTMLTableSectionElement.webidl \
   HTMLTextAreaElement.webidl \
+  HTMLTimeElement.webidl \
   HTMLTitleElement.webidl \
   HTMLUListElement.webidl \
   ImageData.webidl \
   LinkStyle.webidl \
   LocalMediaStream.webidl \
   Location.webidl \
   MediaStream.webidl \
   MutationObserver.webidl \
--- a/editor/libeditor/base/nsEditPropertyAtomList.h
+++ b/editor/libeditor/base/nsEditPropertyAtomList.h
@@ -145,13 +145,14 @@ EDITOR_ATOM(sub, "sub")
 EDITOR_ATOM(sup, "sup")
 EDITOR_ATOM(table, "table")
 EDITOR_ATOM(tbody, "tbody")
 EDITOR_ATOM(td, "td")
 EDITOR_ATOM(textarea, "textarea")
 EDITOR_ATOM(tfoot, "tfoot")
 EDITOR_ATOM(thead, "thead")
 EDITOR_ATOM(th, "th")
+EDITOR_ATOM(time, "time")
 EDITOR_ATOM(tr, "tr")
 EDITOR_ATOM(tt, "tt")
 EDITOR_ATOM(ul, "ul")
 EDITOR_ATOM(u, "u")
 EDITOR_ATOM(var, "var")
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -745,16 +745,17 @@ static const nsElementInfo kElements[eHT
   ELEM(sup, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
   ELEM(table, true, false, GROUP_BLOCK, GROUP_TABLE_CONTENT),
   ELEM(tbody, true, false, GROUP_TABLE_CONTENT, GROUP_TBODY_CONTENT),
   ELEM(td, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
   ELEM(textarea, true, false, GROUP_FORMCONTROL, GROUP_LEAF),
   ELEM(tfoot, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
   ELEM(th, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
   ELEM(thead, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
+  ELEM(time, true, false, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
   ELEM(title, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF),
   ELEM(tr, true, false, GROUP_TBODY_CONTENT, GROUP_TR_CONTENT),
   ELEM(tt, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
   ELEM(u, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
   // XXX Can contain self and ol because editor does sublists illegally.
   ELEM(ul, true, true, GROUP_BLOCK | GROUP_OL_UL,
        GROUP_LI | GROUP_OL_UL),
   ELEM(var, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
--- a/parser/htmlparser/public/nsHTMLTagList.h
+++ b/parser/htmlparser/public/nsHTMLTagList.h
@@ -148,16 +148,17 @@ HTML_HTMLELEMENT_TAG(sub)
 HTML_HTMLELEMENT_TAG(sup)
 HTML_TAG(table, Table)
 HTML_TAG(tbody, TableSection)
 HTML_TAG(td, TableCell)
 HTML_TAG(textarea, TextArea)
 HTML_TAG(tfoot, TableSection)
 HTML_TAG(th, TableCell)
 HTML_TAG(thead, TableSection)
+HTML_TAG(time, Time)
 HTML_TAG(title, Title)
 HTML_TAG(tr, TableRow)
 HTML_HTMLELEMENT_TAG(tt)
 HTML_HTMLELEMENT_TAG(u)
 HTML_TAG(ul, SharedList)
 HTML_HTMLELEMENT_TAG(var)
 #if defined(MOZ_MEDIA)
 HTML_TAG(video, Video)
--- a/parser/htmlparser/src/nsElementTable.cpp
+++ b/parser/htmlparser/src/nsElementTable.cpp
@@ -1197,16 +1197,25 @@ const nsHTMLElement gHTMLElements[] = {
     /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,  //fix bug 54840...
     /*rootnodes,endrootnodes*/          &gInTable,&gInTable,  
     /*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
     /*parent,incl,exclgroups*/          kNone, kNone, kSelf,
     /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
     /*special parents,kids*/            &gInTable,&gTableElemKids,
   },
   {
+    /*tag*/                             eHTMLTag_time,
+    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
+    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
+    /*autoclose starttags and endtags*/ 0,0,0,0,
+    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
+    /*special props, prop-range*/       0, kDefaultPropRange,
+    /*special parents,kids*/            0,0,
+  },
+  {
     /*tag*/                             eHTMLTag_title,
     /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
     /*rootnodes,endrootnodes*/          &gInHead,&gInHead,
     /*autoclose starttags and endtags*/ 0,0,0,0,
     /*parent,incl,exclgroups*/          kHeadContent,kPCDATA, kNone,
     /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,
     /*special parents,kids*/            &gInHead,&gContainsText,
   },
--- a/parser/htmlparser/src/nsHTMLTags.cpp
+++ b/parser/htmlparser/src/nsHTMLTags.cpp
@@ -250,16 +250,18 @@ static const PRUnichar sHTMLTagUnicodeNa
 static const PRUnichar sHTMLTagUnicodeName_textarea[] =
   {'t', 'e', 'x', 't', 'a', 'r', 'e', 'a', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_tfoot[] =
   {'t', 'f', 'o', 'o', 't', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_th[] =
   {'t', 'h', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_thead[] =
   {'t', 'h', 'e', 'a', 'd', '\0'};
+static const PRUnichar sHTMLTagUnicodeName_time[] =
+  {'t', 'i', 'm', 'e', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_title[] =
   {'t', 'i', 't', 'l', 'e', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_tr[] =
   {'t', 'r', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_tt[] =
   {'t', 't', '\0'};
 static const PRUnichar sHTMLTagUnicodeName_u[] =
   {'u', '\0'};