Merge latest green fx-team changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 31 Jul 2013 13:02:44 +0100
changeset 148309 ffd57aa81b5f370a67ae0c0bbd539d6d228154ed
parent 148308 99e620258012b5d364fc3f2676e953492c179853 (current diff)
parent 148295 0ecb8e64dc08b38ca567edb6937814b2972dbff4 (diff)
child 148323 c4dd1430498add735cd0f1b76eaf0b548b288f73
child 148327 ee5c1138cbfd762099377bbe680cbb99c855742f
child 148340 a3d8476211b36728589d712b4bb1deae5ef11334
push id4085
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 20:29:25 +0000
treeherdermozilla-aurora@ede8780a15bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
Merge latest green fx-team changeset and mozilla-central
layout/base/nsStyleConsts.h
layout/generic/nsTextFrameThebes.cpp
toolkit/crashreporter/breakpad-patches/12-sht-arm-exidx-define.patch
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "7e8284bea36c2d9307f919090922d3885f67eafc", 
+    "revision": "12379f829ad18e0562c527e685e376ffc4c48994", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/metro/base/content/Util.js
+++ b/browser/metro/base/content/Util.js
@@ -222,18 +222,18 @@ let Util = {
             aElement.getAttributeNS(kXLinkNamespace, "type") == "simple");
   },
 
   isText: function isText(aElement) {
     return (aElement instanceof Ci.nsIDOMHTMLParagraphElement ||
             aElement instanceof Ci.nsIDOMHTMLDivElement ||
             aElement instanceof Ci.nsIDOMHTMLLIElement ||
             aElement instanceof Ci.nsIDOMHTMLPreElement ||
-            aElement instanceof HTMLHeadingElement ||
-            aElement instanceof HTMLTableCellElement ||
+            aElement instanceof Ci.nsIDOMHTMLHeadingElement ||
+            aElement instanceof Ci.nsIDOMHTMLTableCellElement ||
             aElement instanceof Ci.nsIDOMHTMLBodyElement);
   },
 
   /*
    * Rect and nsIDOMRect utilities
    */
 
   getCleanRect: function getCleanRect() {
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -1180,26 +1180,26 @@ var StartUI = {
       // of the keyboard transition.
       ContentAreaObserver.navBarWillBlur();
     }
 
     if (aEvent.button == 0)
       ContextUI.dismissTabs();
   },
 
-  onNarrowTitleClick: function onNarrowTitleClick(gridId) {
-    let grid = document.getElementById(gridId);
+  onNarrowTitleClick: function onNarrowTitleClick(sectionId) {
+    let section = document.getElementById(sectionId);
 
-    if (grid.hasAttribute("expanded"))
+    if (section.hasAttribute("expanded"))
       return;
 
-    for (let expandedGrid of Elements.startUI.querySelectorAll("[expanded]"))
-      expandedGrid.removeAttribute("expanded")
+    for (let expandedSection of Elements.startUI.querySelectorAll(".meta-section[expanded]"))
+      expandedSection.removeAttribute("expanded")
 
-    grid.setAttribute("expanded", "true");
+    section.setAttribute("expanded", "true");
   },
 
   handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
       case "contextmenu":
         let event = document.createEvent("Events");
         event.initEvent("MozEdgeUICompleted", true, false);
         window.dispatchEvent(event);
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -192,41 +192,45 @@
           </vbox>
         </hbox>
 
         <!-- Start UI -->
         <hbox id="start-container" flex="1" observes="bcast_windowState" class="meta content-height content-width">
           <!-- portrait/landscape/filled view -->
 
           <scrollbox id="start-scrollbox" observes="bcast_preciseInput" flex="1">
-            <vbox id="start-topsites" class="meta-section">
+            <vbox id="start-topsites" class="meta-section" expanded="true">
               <label class="meta-section-title wide-title" value="&topSitesHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedTopSitesHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-topsites-grid')"/>
-              <richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1" expanded="true"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-topsites')">
+                &narrowTopSitesHeader.label;
+              </html:div>
+              <richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-bookmarks" class="meta-section">
               <label class="meta-section-title wide-title" value="&bookmarksHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedBookmarksHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-bookmarks-grid')"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-bookmarks')">
+                &narrowBookmarksHeader.label;
+              </html:div>
               <richgrid id="start-bookmarks-grid" set-name="bookmarks" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-history" class="meta-section">
               <label class="meta-section-title wide-title" value="&recentHistoryHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedRecentHistoryHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-history-grid')"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-history')">
+                &narrowRecentHistoryHeader.label;
+              </html:div>
               <richgrid id="start-history-grid" set-name="recentHistory" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-remotetabs" class="meta-section">
               <label class="meta-section-title wide-title" value="&remoteTabsHeader.label;"/>
-              <label id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" value="&snappedRemoteTabsHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-remotetabs-grid')"/>
+              <html:div id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-remotetabs')">
+                &narrowRemoteTabsHeader.label;
+              </html:div>
               <richgrid id="start-remotetabs-grid" set-name="remoteTabs" seltype="multiple" flex="1"/>
             </vbox>
 
             <!-- Spacer to take extra space in snapped mode. -->
             <spacer flex="999"/>
           </scrollbox>
 
         </hbox>
--- a/browser/metro/base/content/contenthandlers/FormHelper.js
+++ b/browser/metro/base/content/contenthandlers/FormHelper.js
@@ -10,16 +10,17 @@ dump("### FormHelper.js loaded\n");
 
 let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
 let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
 let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
 let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
 let HTMLDocument = Ci.nsIDOMHTMLDocument;
 let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
 let HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
+let HTMLLabelElement = Ci.nsIDOMHTMLLabelElement;
 let HTMLButtonElement = Ci.nsIDOMHTMLButtonElement;
 let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
 let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
 let XULMenuListElement = Ci.nsIDOMXULMenuListElement;
 
 /**
  * Responsible of navigation between forms fields and of the opening of the assistant
  */
--- a/browser/metro/locales/en-US/chrome/browser.dtd
+++ b/browser/metro/locales/en-US/chrome/browser.dtd
@@ -20,27 +20,27 @@
 <!ENTITY appbarFindInPage2.label    "Find in page">
 <!ENTITY appbarViewOnDesktop2.label "View on desktop">
 
 <!ENTITY topSitesHeader.label        "Top Sites">
 <!ENTITY bookmarksHeader.label       "Bookmarks">
 <!ENTITY recentHistoryHeader.label   "Recent History">
 <!ENTITY remoteTabsHeader.label      "Tabs from Other Devices">
 
-<!-- LOCALIZATION NOTE (snappedRemoteTabsHeader.label): shortened version of startRemoteTabsHeader.label.
-     Needs to be two words or shorter to fit in narrow vertical space.-->
-<!-- LOCALIZATION NOTE (snappedRemoteTabsHeader.label,
-                        snappedBookmarksHeader.label,
-                        snappedHistoryHeader.label,
-                        snappedTopSitesHeader.label )
-      The '>' character is not part of the name, but is an indicator of more content. Please do not localize the '>' -->
-<!ENTITY snappedRemoteTabsHeader.label    "Remote Tabs >">
-<!ENTITY snappedBookmarksHeader.label     "Bookmarks >">
-<!ENTITY snappedRecentHistoryHeader.label "Recent History >">
-<!ENTITY snappedTopSitesHeader.label      "Top Sites >">
+<!-- LOCALIZATION NOTE (narrowTopSitesHeader.label,
+                        narrowBookmarksHeader.label,
+                        narrowHistoryHeader.label,
+                        narrowRemoteTabsHeader.label )
+     are shortened versions of topSitesHeader.label, bookmarksHeader.label, recentHistoryHeader.label
+     and remoteTabsHeader.label. Need to be two words or shorter to fit in narrow vertical space.
+      -->
+<!ENTITY narrowTopSitesHeader.label      "Top Sites">
+<!ENTITY narrowBookmarksHeader.label     "Bookmarks">
+<!ENTITY narrowRecentHistoryHeader.label "Recent History">
+<!ENTITY narrowRemoteTabsHeader.label    "Remote Tabs">
 
 <!ENTITY downloadsHeader.label     "Downloads">
 <!ENTITY downloadShowPage.label    "Go to Page">
 <!ENTITY downloadShow2.label       "Find">
 <!ENTITY downloadOpen2.label       "Open">
 <!ENTITY downloadCancel.label      "Cancel">
 <!ENTITY downloadPause.label       "Pause">
 <!ENTITY downloadResume.label      "Resume">
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -244,17 +244,17 @@ documenttab[selected] .documenttab-selec
   min-width: @grid_double_column_width@;
   -moz-box-flex: 1;
   -moz-box-align: center;
 }
 #start-container[viewstate="snapped"] richgrid {
   visibility: collapse;
 }
 
-#start-container[viewstate="snapped"] richgrid[expanded] {
+#start-container[viewstate="snapped"] .meta-section[expanded] > richgrid {
   visibility: visible;
 }
 
 /* Browser Content Areas ==================================================== */
 
 /* Hide the browser while the start UI is visible */
 #content-viewport[startpage],
 #content-viewport[filtering] {
--- a/browser/metro/theme/platform.css
+++ b/browser/metro/theme/platform.css
@@ -648,28 +648,41 @@ arrowbox {
   background-image: url("chrome://browser/skin/images/firefox-watermark.png");
   background-repeat: no-repeat;
   background-position: center center;
   padding: @metro_spacing_normal@ @metro_spacing_xxnormal@;
   overflow: auto;
   max-width: 100%;
   width: 100%;
 }
+
 .meta-section {
   margin: 0 @metro_spacing_large@;
 }
+
 .meta-section-title {
   font-size: @metro_font_large@;
   font-weight: 100;
   display: none;
+  cursor: default;
 }
+
 #start-container[viewstate="snapped"] .meta-section-title.narrow-title,
 #start-container:not([viewstate="snapped"]) .meta-section-title.wide-title {
   display: block;
 }
+
+.meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(ltr):after {
+  content: ">";
+}
+
+.meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(rtl):before {
+  content: "<";
+}
+
 /* App bars ----------------------------------------------------------------- */
 appbar {
   display: block;
   position: fixed;
   bottom: 0;
   width: 100%;
   transform: translateY(100%);
   transition: transform @metro_animation_duration@ @metro_animation_easing@;
--- a/build/autoconf/libstdcxx.py
+++ b/build/autoconf/libstdcxx.py
@@ -56,16 +56,18 @@ def encode_ver(v):
 def find_version(e):
     """Given the value of environment variable CXX or HOST_CXX, find the
     version of the libstdc++ it uses.
     """
     args = e.split()
     args +=  ['-shared', '-Wl,-t']
     p = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
     candidates = [x for x in p.stdout if 'libstdc++.so' in x]
+    if not candidates:
+        return ''
     assert len(candidates) == 1
     libstdcxx = parse_ld_line(candidates[-1])
 
     p = subprocess.Popen(['readelf', '-V', libstdcxx], stdout=subprocess.PIPE)
     versions = [parse_readelf_line(x)
                 for x in p.stdout.readlines() if 'Name: GLIBCXX' in x]
     last_version = sorted(versions, cmp = cmp_ver)[-1]
     return encode_ver(last_version)
--- a/build/unix/moz.build
+++ b/build/unix/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-if CONFIG['STDCXX_COMPAT']:
+if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION'] or CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
     DIRS += ['stdc++compat']
 
 if CONFIG['USE_ELF_HACK']:
     DIRS += ['elfhack']
 
 TEST_DIRS += ['test']
 
 MODULE = 'build'
--- a/build/unix/stdc++compat/Makefile.in
+++ b/build/unix/stdc++compat/Makefile.in
@@ -9,16 +9,16 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 FORCE_STATIC_LIB= 1
 STL_FLAGS =
 NO_EXPAND_LIBS = 1
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 
-  $(NULL)
-
-HOST_CPPSRCS = $(CPPSRCS)
+ifdef MOZ_LIBSTDCXX_HOST_VERSION
+HOST_CPPSRCS = stdc++compat.cpp
+endif
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION)
-HOST_CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION)
+HOST_CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_HOST_VERSION)
--- a/build/unix/stdc++compat/moz.build
+++ b/build/unix/stdc++compat/moz.build
@@ -1,16 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 MODULE = 'build'
 
-CPP_SOURCES += [
-    'stdc++compat.cpp',
-]
+if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
+    LIBRARY_NAME = 'stdc++compat'
+    CPP_SOURCES += ['stdc++compat.cpp']
 
-HOST_LIBRARY_NAME = 'host_stdc++compat'
+if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
+    HOST_LIBRARY_NAME = 'host_stdc++compat'
 
-LIBRARY_NAME = 'stdc++compat'
-
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -12,17 +12,17 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 # For sanity's sake, we compile nsinstall without the wrapped system
 # headers, so that we can use it to set up the wrapped system headers.
 VISIBILITY_FLAGS =
 
 # STDCXX_COMPAT is not needed here, and will actually fail because
 # libstdc++-compat is not built yet.
-STDCXX_COMPAT =
+MOZ_LIBSTDCXX_HOST_VERSION =
 
 ifneq (WINNT,$(HOST_OS_ARCH))
 HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 endif
 
 ifndef CROSS_COMPILE
 ifdef USE_ELF_DYNSTR_GC
 export:: elf-dynstr-gc
--- a/config/config.mk
+++ b/config/config.mk
@@ -742,24 +742,28 @@ EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselis
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
 
-ifdef STDCXX_COMPAT
+ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
 ifneq ($(OS_ARCH),Darwin)
 CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
 endif
 
+ifdef MOZ_LIBSTDCXX_TARGET_VERSION
 EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,stdc++compat,$(DEPTH)/build/unix/stdc++compat)
+endif
+ifdef MOZ_LIBSTDCXX_HOST_VERSION
 HOST_EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,host_stdc++compat,$(DEPTH)/build/unix/stdc++compat)
 endif
+endif
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
 # we overwrite the ojects from the first pass with those from the second,
--- a/configure.in
+++ b/configure.in
@@ -7529,20 +7529,18 @@ dnl ====================================
 dnl = libstdc++ compatibility hacks
 dnl ========================================================
 
 STDCXX_COMPAT=
 MOZ_ARG_ENABLE_BOOL(stdcxx-compat,
 [  --enable-stdcxx-compat  Enable compatibility with older libstdc++],
     STDCXX_COMPAT=1)
 
-AC_SUBST(STDCXX_COMPAT)
-
 if test -n "$STDCXX_COMPAT"; then
-   eval $(CXX="$CXX" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
+   eval $(CXX="$CXX" HOST_CXX="$HOST_CXX" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
    AC_SUBST(MOZ_LIBSTDCXX_TARGET_VERSION)
    AC_SUBST(MOZ_LIBSTDCXX_HOST_VERSION)
 fi
 
 dnl ========================================================
 dnl =
 dnl = Profiling and Instrumenting
 dnl =
--- a/content/html/content/src/HTMLDataListElement.cpp
+++ b/content/html/content/src/HTMLDataListElement.cpp
@@ -22,25 +22,36 @@ HTMLDataListElement::WrapNode(JSContext 
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(HTMLDataListElement, nsGenericHTMLElement,
                                      mOptions)
 
 NS_IMPL_ADDREF_INHERITED(HTMLDataListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLDataListElement, Element)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLDataListElement,
+                                nsIDOMHTMLDataListElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLDataListElement)
 
 bool
 HTMLDataListElement::MatchOptions(nsIContent* aContent, int32_t aNamespaceID,
                                   nsIAtom* aAtom, void* aData)
 {
   return aContent->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML) &&
          !aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
 }
 
+NS_IMETHODIMP
+HTMLDataListElement::GetOptions(nsIDOMHTMLCollection** aOptions)
+{
+  NS_ADDREF(*aOptions = Options());
+
+  return NS_OK;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLDataListElement.h
+++ b/content/html/content/src/HTMLDataListElement.h
@@ -2,23 +2,24 @@
 /* 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 HTMLDataListElement_h___
 #define HTMLDataListElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLDataListElement.h"
 #include "nsContentList.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLDataListElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLDataListElement
 {
 public:
   HTMLDataListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLDataListElement();
 
@@ -29,16 +30,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLDataListElement
+  NS_DECL_NSIDOMHTMLDATALISTELEMENT
+
   nsContentList* Options()
   {
     if (!mOptions) {
       mOptions = new nsContentList(this, MatchOptions, nullptr, nullptr, true);
     }
 
     return mOptions;
   }
--- a/content/html/content/src/HTMLFontElement.cpp
+++ b/content/html/content/src/HTMLFontElement.cpp
@@ -26,23 +26,76 @@ HTMLFontElement::WrapNode(JSContext *aCx
 {
   return HTMLFontElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLFontElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLFontElement, Element)
 
 // QueryInterface implementation for HTMLFontElement
-NS_INTERFACE_MAP_BEGIN(HTMLFontElement)
+NS_INTERFACE_TABLE_HEAD(HTMLFontElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLFontElement, nsIDOMHTMLFontElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLFontElement)
 
+NS_IMETHODIMP
+HTMLFontElement::GetColor(nsAString& aColor)
+{
+  nsString color;
+  GetColor(color);
+  aColor = color;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetColor(const nsAString& aColor)
+{
+  ErrorResult rv;
+  SetColor(aColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLFontElement::GetFace(nsAString& aFace)
+{
+  nsString face;
+  GetFace(face);
+  aFace = face;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetFace(const nsAString& aFace)
+{
+  ErrorResult rv;
+  SetFace(aFace, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLFontElement::GetSize(nsAString& aSize)
+{
+  nsString size;
+  GetSize(size);
+  aSize = size;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetSize(const nsAString& aSize)
+{
+  ErrorResult rv;
+  SetSize(aSize, rv);
+  return rv.ErrorCode();
+}
+
 bool
 HTMLFontElement::ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::size) {
--- a/content/html/content/src/HTMLFontElement.h
+++ b/content/html/content/src/HTMLFontElement.h
@@ -2,22 +2,23 @@
 /* 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 HTMLFontElement_h___
 #define HTMLFontElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLFontElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLFontElement MOZ_FINAL : public nsGenericHTMLElement,
-                                  public nsIDOMHTMLElement
+                                  public nsIDOMHTMLFontElement
 {
 public:
   HTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLFontElement();
 
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLFontElement
+  NS_DECL_NSIDOMHTMLFONTELEMENT
+
   void GetColor(nsString& aColor)
   {
     GetHTMLAttr(nsGkAtoms::color, aColor);
   }
   void SetColor(const nsAString& aColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::color, aColor, aError);
   }
--- a/content/html/content/src/HTMLHeadingElement.cpp
+++ b/content/html/content/src/HTMLHeadingElement.cpp
@@ -21,29 +21,35 @@ namespace dom {
 HTMLHeadingElement::~HTMLHeadingElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLHeadingElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLHeadingElement, Element)
 
 // QueryInterface implementation for HTMLHeadingElement
-NS_INTERFACE_MAP_BEGIN(HTMLHeadingElement)
+NS_INTERFACE_TABLE_HEAD(HTMLHeadingElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLHeadingElement,
+                                nsIDOMHTMLHeadingElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLHeadingElement)
 
 JSObject*
 HTMLHeadingElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLHeadingElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_STRING_ATTR(HTMLHeadingElement, Align, align)
+
+
 bool
 HTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
                                    nsIAtom* aAttribute,
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
--- a/content/html/content/src/HTMLHeadingElement.h
+++ b/content/html/content/src/HTMLHeadingElement.h
@@ -2,23 +2,24 @@
 /* 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_HTMLHeadingElement_h
 #define mozilla_dom_HTMLHeadingElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLHeadingElement.h"
 #include "nsGenericHTMLElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLHeadingElement MOZ_FINAL : public nsGenericHTMLElement,
-                                     public nsIDOMHTMLElement
+				     public nsIDOMHTMLHeadingElement
 {
 public:
   HTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLHeadingElement();
 
@@ -29,34 +30,30 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLHeadingElement
+  NS_DECL_NSIDOMHTMLHEADINGELEMENT
+
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
-  void GetAlign(nsAString& aAlign)
-  {
-    GetHTMLAttr(nsGkAtoms::align, aAlign);
-  }
-  void SetAlign(const nsAString& aAlign, ErrorResult& aRv)
-  {
-    SetHTMLAttr(nsGkAtoms::align, aAlign, aRv);
-  }
-
+  // The XPCOM versions of GetAlign and SetAlign are fine for us for
+  // use from WebIDL.
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
 } // namespace mozilla
 } // namespace dom
--- a/content/html/content/src/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -30,23 +30,59 @@ HTMLLabelElement::WrapNode(JSContext *aC
 
 // nsISupports
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLLabelElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLabelElement, Element)
 
 // QueryInterface implementation for HTMLLabelElement
-NS_INTERFACE_MAP_BEGIN(HTMLLabelElement)
+NS_INTERFACE_TABLE_HEAD(HTMLLabelElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLLabelElement,
+                                nsIDOMHTMLLabelElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
+// nsIDOMHTMLLabelElement
+
 NS_IMPL_ELEMENT_CLONE(HTMLLabelElement)
 
+NS_IMETHODIMP
+HTMLLabelElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::GetControl(nsIDOMHTMLElement** aElement)
+{
+  nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(GetLabeledElement());
+  element.forget(aElement);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::SetHtmlFor(const nsAString& aHtmlFor)
+{
+  ErrorResult rv;
+  SetHtmlFor(aHtmlFor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::GetHtmlFor(nsAString& aHtmlFor)
+{
+  nsString htmlFor;
+  GetHtmlFor(htmlFor);
+  aHtmlFor = htmlFor;
+  return NS_OK;
+}
+
 void
 HTMLLabelElement::Focus(ErrorResult& aError)
 {
   // retarget the focus method at the for content
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetLabeledElement());
     if (elem)
--- a/content/html/content/src/HTMLLabelElement.h
+++ b/content/html/content/src/HTMLLabelElement.h
@@ -6,22 +6,23 @@
 /**
  * Declaration of HTML <label> elements.
  */
 #ifndef HTMLLabelElement_h
 #define HTMLLabelElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLLabelElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLabelElement MOZ_FINAL : public nsGenericHTMLFormElement,
-                                   public nsIDOMHTMLElement
+                                   public nsIDOMHTMLLabelElement
 {
 public:
   HTMLLabelElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLFormElement(aNodeInfo),
       mHandlingEvent(false)
   {
   }
   virtual ~HTMLLabelElement();
@@ -32,16 +33,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLLabelElement
+  NS_DECL_NSIDOMHTMLLABELELEMENT
+
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   using nsGenericHTMLFormElement::GetForm;
   void GetHtmlFor(nsString& aHtmlFor)
   {
     GetHTMLAttr(nsGkAtoms::_for, aHtmlFor);
   }
--- a/content/html/content/src/HTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -20,23 +20,40 @@ HTMLLegendElement::~HTMLLegendElement()
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLLegendElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLegendElement, Element)
 
 
 // QueryInterface implementation for HTMLLegendElement
-NS_INTERFACE_MAP_BEGIN(HTMLLegendElement)
+NS_INTERFACE_TABLE_HEAD(HTMLLegendElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLLegendElement, nsIDOMHTMLLegendElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
+// nsIDOMHTMLLegendElement
+
+
 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
+
+NS_IMETHODIMP
+HTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  Element* form = GetFormElement();
+
+  return form ? CallQueryInterface(form, aForm) : NS_OK;
+}
+
+
+NS_IMPL_STRING_ATTR(HTMLLegendElement, Align, align)
+
 // this contains center, because IE4 does
 static const nsAttrValue::EnumTable kAlignTable[] = {
   { "left", NS_STYLE_TEXT_ALIGN_LEFT },
   { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
   { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
   { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
   { 0 }
--- a/content/html/content/src/HTMLLegendElement.h
+++ b/content/html/content/src/HTMLLegendElement.h
@@ -2,24 +2,25 @@
 /* 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_HTMLLegendElement_h
 #define mozilla_dom_HTMLLegendElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/HTMLFormElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLegendElement MOZ_FINAL : public nsGenericHTMLElement,
-                                    public nsIDOMHTMLElement
+                                    public nsIDOMHTMLLegendElement
 {
 public:
   HTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLLegendElement();
 
@@ -29,16 +30,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLLegendElement
+  NS_DECL_NSIDOMHTMLLEGENDELEMENT
+
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
 
   virtual void PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) MOZ_OVERRIDE;
 
@@ -77,21 +81,17 @@ public:
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   /**
    * WebIDL Interface
    */
 
   already_AddRefed<HTMLFormElement> GetForm();
 
-  void GetAlign(nsAString& aAlign)
-  {
-    GetHTMLAttr(nsGkAtoms::align, aAlign);
-  }
-
+  // The XPCOM GetAlign is OK for us
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   nsINode* GetParentObject() {
     Element* form = GetFormElement();
     return form ? static_cast<nsINode*>(form)
--- a/content/html/content/src/HTMLMeterElement.cpp
+++ b/content/html/content/src/HTMLMeterElement.cpp
@@ -24,18 +24,21 @@ HTMLMeterElement::HTMLMeterElement(alrea
 HTMLMeterElement::~HTMLMeterElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLMeterElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLMeterElement, Element)
 
 
-NS_INTERFACE_MAP_BEGIN(HTMLMeterElement)
+NS_INTERFACE_TABLE_HEAD(HTMLMeterElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLMeterElement,
+                                nsIDOMHTMLMeterElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLMeterElement)
 
 
 nsEventStates
 HTMLMeterElement::IntrinsicState() const
 {
@@ -215,16 +218,98 @@ HTMLMeterElement::Optimum() const
 
   if (optimum <= min) {
     return min;
   }
 
   return std::min(optimum, max);
 }
 
+/*
+ * XPCOM methods
+ */
+
+NS_IMETHODIMP
+HTMLMeterElement::GetMin(double* aValue)
+{
+  *aValue = Min();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetMin(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::min, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetMax(double* aValue)
+{
+  *aValue = Max();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetMax(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::max, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetValue(double* aValue)
+{
+  *aValue = Value();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetValue(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::value, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetLow(double* aValue)
+{
+  *aValue = Low();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetLow(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::low, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetHigh(double* aValue)
+{
+  *aValue = High();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetHigh(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::high, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetOptimum(double* aValue)
+{
+  *aValue = Optimum();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetOptimum(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::optimum, aValue);
+}
+
 nsEventStates
 HTMLMeterElement::GetOptimumState() const
 {
   /*
    * If the optimum value is in [minimum, low[,
    *     return if the value is in optimal, suboptimal or sub-suboptimal region
    *
    * If the optimum value is in [low, high],
--- a/content/html/content/src/HTMLMeterElement.h
+++ b/content/html/content/src/HTMLMeterElement.h
@@ -2,28 +2,29 @@
 /* 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_HTMLMeterElement_h
 #define mozilla_dom_HTMLMeterElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLMeterElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include "nsAlgorithm.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMeterElement MOZ_FINAL : public nsGenericHTMLElement,
-                                   public nsIDOMHTMLElement
+                                   public nsIDOMHTMLMeterElement
 {
 public:
   HTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLMeterElement();
 
   /* nsISupports */
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -31,67 +32,70 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   /* nsIDOMElement */
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   /* nsIDOMHTMLElement */
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  /* nsIDOMHTMLMeterElement */
+  NS_DECL_NSIDOMHTMLMETERELEMENT
+
   virtual nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                       const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   // WebIDL
 
   /* @return the value */
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::value, aValue);
+    aRv = SetValue(aValue);
   }
 
   /* @return the minimum value */
   double Min() const;
   void SetMin(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::min, aValue);
+    aRv = SetMin(aValue);
   }
 
   /* @return the maximum value */
   double Max() const;
   void SetMax(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::max, aValue);
+    aRv = SetMax(aValue);
   }
 
   /* @return the low value */
   double Low() const;
   void SetLow(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::low, aValue);
+    aRv = SetLow(aValue);
   }
 
   /* @return the high value */
   double High() const;
   void SetHigh(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::high, aValue);
+    aRv = SetHigh(aValue);
   }
 
   /* @return the optimum value */
   double Optimum() const;
   void SetOptimum(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::optimum, aValue);
+    aRv = SetOptimum(aValue);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
 private:
 
--- a/content/html/content/src/HTMLModElement.cpp
+++ b/content/html/content/src/HTMLModElement.cpp
@@ -21,23 +21,30 @@ HTMLModElement::~HTMLModElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLModElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLModElement, Element)
 
 // QueryInterface implementation for HTMLModElement
-NS_INTERFACE_MAP_BEGIN(HTMLModElement)
+NS_INTERFACE_TABLE_HEAD(HTMLModElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLModElement,
+                                nsIDOMHTMLModElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLModElement)
 
+
+NS_IMPL_URI_ATTR(HTMLModElement, Cite, cite)
+NS_IMPL_STRING_ATTR(HTMLModElement, DateTime, datetime)
+
 JSObject*
 HTMLModElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLModElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLModElement.h
+++ b/content/html/content/src/HTMLModElement.h
@@ -3,23 +3,24 @@
  * 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_HTMLModElement_h
 #define mozilla_dom_HTMLModElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLModElement.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLModElement MOZ_FINAL : public nsGenericHTMLElement,
-                                 public nsIDOMHTMLElement
+                                 public nsIDOMHTMLModElement
 {
 public:
   HTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLModElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -27,32 +28,32 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLModElement
+  NS_DECL_NSIDOMHTMLMODELEMENT
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   void GetCite(nsString& aCite)
   {
     GetHTMLURIAttr(nsGkAtoms::cite, aCite);
   }
   void SetCite(const nsAString& aCite, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::cite, aCite, aRv);
   }
-  void GetDateTime(nsAString& aDateTime)
-  {
-    GetHTMLAttr(nsGkAtoms::datetime, aDateTime);
-  }
+  // XPCOM GetDateTime is fine.
   void SetDateTime(const nsAString& aDateTime, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aRv);
   }
 
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
--- a/content/html/content/src/HTMLOutputElement.cpp
+++ b/content/html/content/src/HTMLOutputElement.cpp
@@ -48,30 +48,39 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLOutputElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLOutputElement, Element)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLOutputElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
-  NS_INTERFACE_TABLE_INHERITED2(HTMLOutputElement,
+  NS_INTERFACE_TABLE_INHERITED3(HTMLOutputElement,
+                                nsIDOMHTMLOutputElement,
                                 nsIMutationObserver,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
 
-void
+
+NS_IMPL_STRING_ATTR(HTMLOutputElement, Name, name)
+
+// nsIConstraintValidation
+NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLOutputElement)
+
+NS_IMETHODIMP
 HTMLOutputElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   UpdateState(true);
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLOutputElement::Reset()
 {
   mValueModeFlag = eModeDefault;
   return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
 }
@@ -135,41 +144,77 @@ HTMLOutputElement::BindToTree(nsIDocumen
   // might end up a in a novalidate form, and unlike other form
   // controls that on its own is enough to make change ui-valid state.
   // So just go ahead and update our state now.
   UpdateState(false);
 
   return rv;
 }
 
-void
-HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
+NS_IMETHODIMP
+HTMLOutputElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::GetType(nsAString& aType)
+{
+  aType.AssignLiteral("output");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::GetValue(nsAString& aValue)
+{
+  nsContentUtils::GetNodeTextContent(this, true, aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::SetValue(const nsAString& aValue)
 {
   mValueModeFlag = eModeValue;
-  aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
+  return nsContentUtils::SetNodeTextContent(this, aValue, true);
 }
 
-void
-HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
+NS_IMETHODIMP
+HTMLOutputElement::GetDefaultValue(nsAString& aDefaultValue)
+{
+  aDefaultValue = mDefaultValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue)
 {
   mDefaultValue = aDefaultValue;
   if (mValueModeFlag == eModeDefault) {
-    aRv = nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
+    return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
   }
+
+  return NS_OK;
 }
 
 nsDOMSettableTokenList*
 HTMLOutputElement::HtmlFor()
 {
   if (!mTokenList) {
     mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
   }
   return mTokenList;
 }
 
+NS_IMETHODIMP
+HTMLOutputElement::GetHtmlFor(nsISupports** aResult)
+{
+  NS_ADDREF(*aResult = HtmlFor());
+  return NS_OK;
+}
+
 void HTMLOutputElement::DescendantsChanged()
 {
   if (mValueModeFlag == eModeDefault) {
     nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
   }
 }
 
 // nsIMutationObserver
--- a/content/html/content/src/HTMLOutputElement.h
+++ b/content/html/content/src/HTMLOutputElement.h
@@ -3,24 +3,25 @@
  * 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_HTMLOutputElement_h
 #define mozilla_dom_HTMLOutputElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLOutputElement.h"
 #include "nsStubMutationObserver.h"
 #include "nsIConstraintValidation.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLOutputElement MOZ_FINAL : public nsGenericHTMLFormElement,
-                                    public nsIDOMHTMLElement,
+                                    public nsIDOMHTMLOutputElement,
                                     public nsStubMutationObserver,
                                     public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   HTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLOutputElement();
@@ -32,16 +33,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLOutputElement
+  NS_DECL_NSIDOMHTMLOUTPUTELEMENT
+
   // nsIFormControl
   NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_OUTPUT; }
   NS_IMETHOD Reset() MOZ_OVERRIDE;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) MOZ_OVERRIDE;
 
   virtual bool IsDisabled() const MOZ_OVERRIDE { return false; }
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
@@ -70,50 +74,41 @@ public:
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // WebIDL
   nsDOMSettableTokenList* HtmlFor();
   // nsGenericHTMLFormElement::GetForm is fine.
-  void GetName(nsAString& aName)
-  {
-    GetHTMLAttr(nsGkAtoms::name, aName);
-  }
-
+  using nsGenericHTMLFormElement::GetForm;
+  // XPCOM GetName is fine.
   void SetName(const nsAString& aName, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aRv);
   }
 
-  void GetType(nsAString& aType)
+  // XPCOM GetType is fine.
+  // XPCOM GetDefaultValue is fine.
+  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
   {
-    aType.AssignLiteral("output");
-  }
-
-  void GetDefaultValue(nsAString& aDefaultValue)
-  {
-    aDefaultValue = mDefaultValue;
+    aRv = SetDefaultValue(aDefaultValue);
   }
-
-  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv);
-
-  void GetValue(nsAString& aValue)
+  // XPCOM GetValue is fine.
+  void SetValue(const nsAString& aValue, ErrorResult& aRv)
   {
-    nsContentUtils::GetNodeTextContent(this, true, aValue);
+    aRv = SetValue(aValue);
   }
 
-  void SetValue(const nsAString& aValue, ErrorResult& aRv);
-
   // nsIConstraintValidation::WillValidate is fine.
   // nsIConstraintValidation::Validity() is fine.
   // nsIConstraintValidation::GetValidationMessage() is fine.
   // nsIConstraintValidation::CheckValidity() is fine.
-  void SetCustomValidity(const nsAString& aError);
+  using nsIConstraintValidation::CheckValidity;
+  // nsIConstraintValidation::SetCustomValidity() is fine.
 
 protected:
   enum ValueModeFlag {
     eModeDefault,
     eModeValue
   };
 
   ValueModeFlag                     mValueModeFlag;
--- a/content/html/content/src/HTMLProgressElement.cpp
+++ b/content/html/content/src/HTMLProgressElement.cpp
@@ -26,18 +26,21 @@ HTMLProgressElement::HTMLProgressElement
 HTMLProgressElement::~HTMLProgressElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLProgressElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLProgressElement, Element)
 
 
-NS_INTERFACE_MAP_BEGIN(HTMLProgressElement)
+NS_INTERFACE_TABLE_HEAD(HTMLProgressElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLProgressElement,
+                                nsIDOMHTMLProgressElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLProgressElement)
 
 
 nsEventStates
 HTMLProgressElement::IntrinsicState() const
 {
@@ -59,40 +62,77 @@ HTMLProgressElement::ParseAttribute(int3
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
                                               aValue, aResult);
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::GetValue(double* aValue)
+{
+  *aValue = Value();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Value() const
 {
   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
   if (!attrValue || attrValue->Type() != nsAttrValue::eDoubleValue ||
       attrValue->GetDoubleValue() < 0.0) {
     return kDefaultValue;
   }
 
   return std::min(attrValue->GetDoubleValue(), Max());
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::SetValue(double aValue)
+{
+  ErrorResult rv;
+  SetValue(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLProgressElement::GetMax(double* aValue)
+{
+  *aValue = Max();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Max() const
 {
   const nsAttrValue* attrMax = mAttrsAndChildren.GetAttr(nsGkAtoms::max);
   if (!attrMax || attrMax->Type() != nsAttrValue::eDoubleValue ||
       attrMax->GetDoubleValue() <= 0.0) {
     return kDefaultMax;
   }
 
   return attrMax->GetDoubleValue();
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::SetMax(double aValue)
+{
+  ErrorResult rv;
+  SetMax(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLProgressElement::GetPosition(double* aPosition)
+{
+  *aPosition = Position();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Position() const
 {
   if (IsIndeterminate()) {
     return kIndeterminatePosition;
   }
 
   return Value() / Max();
--- a/content/html/content/src/HTMLProgressElement.h
+++ b/content/html/content/src/HTMLProgressElement.h
@@ -2,27 +2,28 @@
 /* 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_HTMLProgressElement_h
 #define mozilla_dom_HTMLProgressElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLProgressElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLProgressElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLProgressElement
 {
 public:
   HTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLProgressElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -30,16 +31,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLProgressElement
+  NS_DECL_NSIDOMHTMLPROGRESSELEMENT
+
   nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
--- a/content/html/content/src/HTMLSharedElement.cpp
+++ b/content/html/content/src/HTMLSharedElement.cpp
@@ -29,28 +29,38 @@ HTMLSharedElement::~HTMLSharedElement()
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLSharedElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedElement, Element)
 
 // QueryInterface implementation for HTMLSharedElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
-                                       nsIDOMHTMLBaseElement)
+                                       nsIDOMHTMLParamElement)
+  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLParamElement, param)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLBaseElement, base)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDirectoryElement, dir)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, q)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, blockquote)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHeadElement, head)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHtmlElement, html)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedElement)
 
+// nsIDOMHTMLParamElement
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Name, name)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Type, type)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Value, value)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, ValueType, valuetype)
+
+// nsIDOMHTMLDirectoryElement
+NS_IMPL_BOOL_ATTR(HTMLSharedElement, Compact, compact)
+
 // nsIDOMHTMLQuoteElement
 NS_IMPL_URI_ATTR(HTMLSharedElement, Cite, cite)
 
 // nsIDOMHTMLHeadElement
 // Empty
 
 // nsIDOMHTMLHtmlElement
 NS_IMPL_STRING_ATTR(HTMLSharedElement, Version, version)
--- a/content/html/content/src/HTMLSharedElement.h
+++ b/content/html/content/src/HTMLSharedElement.h
@@ -1,32 +1,34 @@
 /* -*- 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_HTMLSharedElement_h
 #define mozilla_dom_HTMLSharedElement_h
 
+#include "nsIDOMHTMLParamElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLDirectoryElement.h"
 #include "nsIDOMHTMLQuoteElement.h"
 #include "nsIDOMHTMLHeadElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
 #include "nsGenericHTMLElement.h"
 
 #include "nsGkAtoms.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Assertions.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedElement MOZ_FINAL : public nsGenericHTMLElement,
+                                    public nsIDOMHTMLParamElement,
                                     public nsIDOMHTMLBaseElement,
                                     public nsIDOMHTMLDirectoryElement,
                                     public nsIDOMHTMLQuoteElement,
                                     public nsIDOMHTMLHeadElement,
                                     public nsIDOMHTMLHtmlElement
 {
 public:
   HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -42,19 +44,25 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLParamElement
+  NS_DECL_NSIDOMHTMLPARAMELEMENT
+
   // nsIDOMHTMLBaseElement
   NS_DECL_NSIDOMHTMLBASEELEMENT
 
+  // nsIDOMHTMLDirectoryElement
+  NS_DECL_NSIDOMHTMLDIRECTORYELEMENT
+
   // nsIDOMHTMLQuoteElement
   NS_DECL_NSIDOMHTMLQUOTEELEMENT
 
   // nsIDOMHTMLHeadElement
   NS_DECL_NSIDOMHTMLHEADELEMENT
 
   // nsIDOMHTMLHtmlElement
   NS_DECL_NSIDOMHTMLHTMLELEMENT
@@ -85,17 +93,17 @@ public:
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE
   {
-    return static_cast<nsIDOMHTMLBaseElement*>(this);
+    return static_cast<nsIDOMHTMLParamElement*>(this);
   }
 
   // WebIDL API
   // HTMLParamElement
   void GetName(DOMString& aValue)
   {
     MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::param));
     GetHTMLAttr(nsGkAtoms::name, aValue);
--- a/content/html/content/src/HTMLSharedListElement.cpp
+++ b/content/html/content/src/HTMLSharedListElement.cpp
@@ -27,16 +27,17 @@ HTMLSharedListElement::~HTMLSharedListEl
 NS_IMPL_ADDREF_INHERITED(HTMLSharedListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedListElement, Element)
 
 // QueryInterface implementation for nsHTMLSharedListElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedListElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
                                        nsIDOMHTMLOListElement)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLOListElement, ol)
+  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDListElement, dl)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLUListElement, ul)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedListElement)
 
 
 NS_IMPL_BOOL_ATTR(HTMLSharedListElement, Compact, compact)
--- a/content/html/content/src/HTMLSharedListElement.h
+++ b/content/html/content/src/HTMLSharedListElement.h
@@ -4,24 +4,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLSharedListElement_h
 #define mozilla_dom_HTMLSharedListElement_h
 #include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsIDOMHTMLOListElement.h"
+#include "nsIDOMHTMLDListElement.h"
 #include "nsIDOMHTMLUListElement.h"
 #include "nsGenericHTMLElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedListElement MOZ_FINAL : public nsGenericHTMLElement,
                                         public nsIDOMHTMLOListElement,
+                                        public nsIDOMHTMLDListElement,
                                         public nsIDOMHTMLUListElement
 {
 public:
   HTMLSharedListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLSharedListElement();
@@ -36,16 +38,19 @@ public:
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   // nsIDOMHTMLOListElement
   NS_DECL_NSIDOMHTMLOLISTELEMENT
 
+  // nsIDOMHTMLDListElement
+  // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
+
   // nsIDOMHTMLUListElement
   // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLTableCellElement.cpp
+++ b/content/html/content/src/HTMLTableCellElement.cpp
@@ -29,18 +29,21 @@ HTMLTableCellElement::WrapNode(JSContext
 {
   return HTMLTableCellElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableCellElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableCellElement, Element)
 
 // QueryInterface implementation for HTMLTableCellElement
-NS_INTERFACE_MAP_BEGIN(HTMLTableCellElement)
+NS_INTERFACE_TABLE_HEAD(HTMLTableCellElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableCellElement,
+                                nsIDOMHTMLTableCellElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)
 
 
 // protected method
 HTMLTableRowElement*
@@ -97,31 +100,270 @@ HTMLTableCellElement::CellIndex() const
       return i;
     }
   }
 
   return -1;
 }
 
 NS_IMETHODIMP
+HTMLTableCellElement::GetCellIndex(int32_t* aCellIndex)
+{
+  *aCellIndex = CellIndex();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (HTMLTableElement* table = GetTable()) {
     nsMappedAttributes* tableInheritedAttributes =
       table->GetAttributesMappedForCell();
     if (tableInheritedAttributes) {
       aRuleWalker->Forward(tableInheritedAttributes);
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+HTMLTableCellElement::SetAbbr(const nsAString& aAbbr)
+{
+  ErrorResult rv;
+  SetAbbr(aAbbr, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAbbr(nsAString& aAbbr)
+{
+  nsString abbr;
+  GetAbbr(abbr);
+  aAbbr = abbr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetAxis(const nsAString& aAxis)
+{
+  ErrorResult rv;
+  SetAxis(aAxis, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAxis(nsAString& aAxis)
+{
+  nsString axis;
+  GetAxis(axis);
+  aAxis = axis;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetHeight(const nsAString& aHeight)
+{
+  ErrorResult rv;
+  SetHeight(aHeight, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetHeight(nsAString& aHeight)
+{
+  nsString height;
+  GetHeight(height);
+  aHeight = height;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetNoWrap(bool aNoWrap)
+{
+  ErrorResult rv;
+  SetNoWrap(aNoWrap, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetNoWrap(bool* aNoWrap)
+{
+  *aNoWrap = NoWrap();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetScope(const nsAString& aScope)
+{
+  ErrorResult rv;
+  SetScope(aScope, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetScope(nsAString& aScope)
+{
+  nsString scope;
+  GetScope(scope);
+  aScope = scope;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetHeaders(const nsAString& aHeaders)
+{
+  ErrorResult rv;
+  SetHeaders(aHeaders, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetHeaders(nsAString& aHeaders)
+{
+  nsString headers;
+  GetHeaders(headers);
+  aHeaders = headers;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetColSpan(int32_t aColSpan)
+{
+  ErrorResult rv;
+  SetColSpan(aColSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetColSpan(int32_t* aColSpan)
+{
+  *aColSpan = ColSpan();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetRowSpan(int32_t aRowSpan)
+{
+  ErrorResult rv;
+  SetRowSpan(aRowSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetRowSpan(int32_t* aRowSpan)
+{
+  *aRowSpan = RowSpan();
+  return NS_OK;
+}
+
 void
 HTMLTableCellElement::GetAlign(nsString& aValue)
 {
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::align, aValue)) {
     // There's no align attribute, ask the row for the alignment.
     HTMLTableRowElement* row = GetRow();
     if (row) {
       row->GetAlign(aValue);
@@ -197,17 +439,17 @@ HTMLTableCellElement::ParseAttribute(int
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static
+static 
 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                            nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // width: value
     nsCSSValue* width = aData->ValueForWidth();
     if (width->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
--- a/content/html/content/src/HTMLTableCellElement.h
+++ b/content/html/content/src/HTMLTableCellElement.h
@@ -2,24 +2,27 @@
 /* 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_HTMLTableCellElement_h
 #define mozilla_dom_HTMLTableCellElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableCellElement.h"
+
+class nsIDOMHTMLTableRowElement;
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableElement;
 
 class HTMLTableCellElement MOZ_FINAL : public nsGenericHTMLElement,
-                                       public nsIDOMHTMLElement
+                                       public nsIDOMHTMLTableCellElement
 {
 public:
   HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLTableCellElement();
 
@@ -30,16 +33,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableCellElement
+  NS_DECL_NSIDOMHTMLTABLECELLELEMENT
+
   uint32_t ColSpan() const
   {
     return GetIntAttr(nsGkAtoms::colspan, 1);
   }
   void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
   {
     SetHTMLIntAttr(nsGkAtoms::colspan, aColSpan, aError);
   }
--- a/content/html/content/src/HTMLTableColElement.cpp
+++ b/content/html/content/src/HTMLTableColElement.cpp
@@ -29,22 +29,125 @@ HTMLTableColElement::WrapNode(JSContext 
 {
   return HTMLTableColElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableColElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableColElement, Element)
 
 // QueryInterface implementation for HTMLTableColElement
-NS_INTERFACE_MAP_BEGIN(HTMLTableColElement)
+NS_INTERFACE_TABLE_HEAD(HTMLTableColElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableColElement,
+                                nsIDOMHTMLTableColElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableColElement)
 
+NS_IMETHODIMP
+HTMLTableColElement::SetSpan(int32_t aSpan)
+{
+  ErrorResult rv;
+  SetSpan(aSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetSpan(int32_t* aSpan)
+{
+  *aSpan = Span();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
 bool
 HTMLTableColElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings ch */
--- a/content/html/content/src/HTMLTableColElement.h
+++ b/content/html/content/src/HTMLTableColElement.h
@@ -2,22 +2,23 @@
 /* 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_HTMLTableColElement_h
 #define mozilla_dom_HTMLTableColElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableColElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableColElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLTableColElement
 {
 public:
   HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLTableColElement();
 
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableColElement
+  NS_DECL_NSIDOMHTMLTABLECOLELEMENT
+
   uint32_t Span() const
   {
     return GetIntAttr(nsGkAtoms::span, 1);
   }
   void SetSpan(uint32_t aSpan, ErrorResult& aError)
   {
     SetHTMLIntAttr(nsGkAtoms::span, aSpan, aError);
   }
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "mozilla/Util.h"
 
 #include "mozilla/dom/HTMLTableElement.h"
+#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsRuleData.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLTableElementBinding.h"
 #include "nsContentUtils.h"
@@ -338,26 +339,246 @@ NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableElement)
 
 
 // the DOM spec says border, cellpadding, cellSpacing are all "wstring"
 // in fact, they are integers or they are meaningless.  so we store them
 // here as ints.
 
+NS_IMETHODIMP
+HTMLTableElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetBorder(const nsAString& aBorder)
+{
+  ErrorResult rv;
+  SetBorder(aBorder, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetBorder(nsAString& aBorder)
+{
+  nsString border;
+  GetBorder(border);
+  aBorder = border;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCellPadding(const nsAString& aCellPadding)
+{
+  ErrorResult rv;
+  SetCellPadding(aCellPadding, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCellPadding(nsAString& aCellPadding)
+{
+  nsString cellPadding;
+  GetCellPadding(cellPadding);
+  aCellPadding = cellPadding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCellSpacing(const nsAString& aCellSpacing)
+{
+  ErrorResult rv;
+  SetCellSpacing(aCellSpacing, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCellSpacing(nsAString& aCellSpacing)
+{
+  nsString cellSpacing;
+  GetCellSpacing(cellSpacing);
+  aCellSpacing = cellSpacing;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetFrame(const nsAString& aFrame)
+{
+  ErrorResult rv;
+  SetFrame(aFrame, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetFrame(nsAString& aFrame)
+{
+  nsString frame;
+  GetFrame(frame);
+  aFrame = frame;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetRules(const nsAString& aRules)
+{
+  ErrorResult rv;
+  SetRules(aRules, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetRules(nsAString& aRules)
+{
+  nsString rules;
+  GetRules(rules);
+  aRules = rules;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetSummary(const nsAString& aSummary)
+{
+  ErrorResult rv;
+  SetSummary(aSummary, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetSummary(nsAString& aSummary)
+{
+  nsString summary;
+  GetSummary(summary);
+  aSummary = summary;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
+{
+  nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption = GetCaption();
+  caption.forget(aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
+{
+  HTMLTableCaptionElement* caption =
+    static_cast<HTMLTableCaptionElement*>(aValue);
+  SetCaption(caption);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
+{
+  NS_IF_ADDREF(*aValue = GetTHead());
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
+{
+  HTMLTableSectionElement* section =
+    static_cast<HTMLTableSectionElement*>(aValue);
+  ErrorResult rv;
+  SetTHead(section, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
+{
+  NS_IF_ADDREF(*aValue = GetTFoot());
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
+{
+  HTMLTableSectionElement* section =
+    static_cast<HTMLTableSectionElement*>(aValue);
+  ErrorResult rv;
+  SetTFoot(section, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Rows());
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableElement::Rows()
 {
   if (!mRows) {
     mRows = new TableRowsCollection(this);
   }
 
   return mRows;
 }
 
+NS_IMETHODIMP
+HTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = TBodies());
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableElement::TBodies()
 {
   if (!mTBodies) {
     // Not using NS_GetContentList because this should not be cached
     mTBodies = new nsContentList(this,
                                  kNameSpaceID_XHTML,
                                  nsGkAtoms::tbody,
@@ -384,25 +605,34 @@ HTMLTableElement::CreateTHead()
     }
 
     ErrorResult rv;
     nsINode::InsertBefore(*head, nsINode::GetFirstChild(), rv);
   }
   return head.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> thead = CreateTHead();
+  return thead ? CallQueryInterface(thead, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteTHead()
 {
   HTMLTableSectionElement* tHead = GetTHead();
   if (tHead) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tHead, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTFoot()
 {
   nsRefPtr<nsGenericHTMLElement> foot = GetTFoot();
   if (!foot) {
     // create a new foot rowgroup
@@ -415,25 +645,34 @@ HTMLTableElement::CreateTFoot()
       return nullptr;
     }
     AppendChildTo(foot, true);
   }
 
   return foot.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> tfoot = CreateTFoot();
+  return tfoot ? CallQueryInterface(tfoot, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteTFoot()
 {
   HTMLTableSectionElement* tFoot = GetTFoot();
   if (tFoot) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tFoot, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateCaption()
 {
   nsRefPtr<nsGenericHTMLElement> caption = GetCaption();
   if (!caption) {
     // Create a new caption.
@@ -446,25 +685,34 @@ HTMLTableElement::CreateCaption()
       return nullptr;
     }
 
     AppendChildTo(caption, true);
   }
   return caption.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> caption = CreateCaption();
+  return caption ? CallQueryInterface(caption, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteCaption()
 {
   HTMLTableCaptionElement* caption = GetCaption();
   if (caption) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*caption, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTBody()
 {
   nsCOMPtr<nsINodeInfo> nodeInfo =
     OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::tbody, nullptr,
                                                kNameSpaceID_XHTML,
@@ -490,17 +738,17 @@ HTMLTableElement::CreateTBody()
 
   return newBody.forget();
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   /* get the ref row at aIndex
-     if there is one,
+     if there is one, 
        get its parent
        insert the new row just before the ref row
      else
        get the first row group
        insert the new row as its first child
   */
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
@@ -595,16 +843,24 @@ HTMLTableElement::InsertRow(int32_t aInd
         rowGroup->InsertBefore(*newRow, rows->Item(0), aError);
       }
     }
   }
 
   return newRow.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableElement::InsertRow(int32_t aIndex, nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> newRow = InsertRow(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(newRow, aValue);
+}
+
 void
 HTMLTableElement::DeleteRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -625,16 +881,24 @@ HTMLTableElement::DeleteRow(int32_t aInd
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   row->RemoveFromParent();
 }
 
+NS_IMETHODIMP
+HTMLTableElement::DeleteRow(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteRow(aValue, rv);
+  return rv.ErrorCode();
+}
+
 static const nsAttrValue::EnumTable kFrameTable[] = {
   { "void",   NS_STYLE_TABLE_FRAME_NONE },
   { "above",  NS_STYLE_TABLE_FRAME_ABOVE },
   { "below",  NS_STYLE_TABLE_FRAME_BELOW },
   { "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
   { "lhs",    NS_STYLE_TABLE_FRAME_LEFT },
   { "rhs",    NS_STYLE_TABLE_FRAME_RIGHT },
   { "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
--- a/content/html/content/src/HTMLTableElement.h
+++ b/content/html/content/src/HTMLTableElement.h
@@ -34,35 +34,33 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableElement
+  NS_DECL_NSIDOMHTMLTABLEELEMENT
+
   HTMLTableCaptionElement* GetCaption() const
   {
     return static_cast<HTMLTableCaptionElement*>(GetChild(nsGkAtoms::caption));
   }
   void SetCaption(HTMLTableCaptionElement* aCaption)
   {
     DeleteCaption();
     if (aCaption) {
       mozilla::ErrorResult rv;
       nsINode::AppendChild(*aCaption, rv);
     }
   }
-
-  void DeleteTFoot();
-
   already_AddRefed<nsGenericHTMLElement> CreateCaption();
 
-  void DeleteCaption();
-
   HTMLTableSectionElement* GetTHead() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::thead));
   }
   void SetTHead(HTMLTableSectionElement* aTHead, ErrorResult& aError)
   {
     if (aTHead && !aTHead->IsHTML(nsGkAtoms::thead)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
@@ -71,18 +69,16 @@ public:
 
     DeleteTHead();
     if (aTHead) {
       nsINode::InsertBefore(*aTHead, nsINode::GetFirstChild(), aError);
     }
   }
   already_AddRefed<nsGenericHTMLElement> CreateTHead();
 
-  void DeleteTHead();
-
   HTMLTableSectionElement* GetTFoot() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::tfoot));
   }
   void SetTFoot(HTMLTableSectionElement* aTFoot, ErrorResult& aError)
   {
     if (aTFoot && !aTFoot->IsHTML(nsGkAtoms::tfoot)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
--- a/content/html/content/src/HTMLTableRowElement.cpp
+++ b/content/html/content/src/HTMLTableRowElement.cpp
@@ -30,35 +30,34 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCells)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableRowElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableRowElement, Element)
 
 // QueryInterface implementation for HTMLTableRowElement
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableRowElement,
+                                nsIDOMHTMLTableRowElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableRowElement)
 
 
 // protected method
-HTMLTableSectionElement*
+already_AddRefed<nsIDOMHTMLTableSectionElement>
 HTMLTableRowElement::GetSection() const
 {
-  nsIContent* parent = GetParent();
-  if (parent->IsHTML() && (parent->Tag() == nsGkAtoms::thead ||
-                           parent->Tag() == nsGkAtoms::tbody ||
-                           parent->Tag() == nsGkAtoms::tfoot)) {
-    return static_cast<HTMLTableSectionElement*>(parent);
-  }
-  return nullptr;
+  nsCOMPtr<nsIDOMHTMLTableSectionElement> section =
+    do_QueryInterface(GetParent());
+  return section.forget();
 }
 
 // protected method
 HTMLTableElement*
 HTMLTableRowElement::GetTable() const
 {
   nsIContent* parent = GetParent();
   if (!parent) {
@@ -90,35 +89,52 @@ HTMLTableRowElement::RowIndex() const
     if (rows->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetRowIndex(int32_t* aValue)
+{
+  *aValue = RowIndex();
+  return NS_OK;
+}
+
 int32_t
 HTMLTableRowElement::SectionRowIndex() const
 {
-  HTMLTableSectionElement* section = GetSection();
+  nsCOMPtr<nsIDOMHTMLTableSectionElement> section = GetSection();
   if (!section) {
     return -1;
   }
 
-  nsCOMPtr<nsIHTMLCollection> coll = section->Rows();
+  nsCOMPtr<nsIDOMHTMLCollection> rows;
+  section->GetRows(getter_AddRefs(rows));
+
+  nsCOMPtr<nsIHTMLCollection> coll = do_QueryInterface(rows);
   uint32_t numRows = coll->Length();
   for (uint32_t i = 0; i < numRows; i++) {
     if (coll->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetSectionRowIndex(int32_t* aValue)
+{
+  *aValue = SectionRowIndex();
+  return NS_OK;
+}
+
 static bool
 IsCell(nsIContent *aContent, int32_t aNamespaceID,
        nsIAtom* aAtom, void *aData)
 {
   nsIAtom* tag = aContent->Tag();
 
   return ((tag == nsGkAtoms::td || tag == nsGkAtoms::th) &&
           aContent->IsHTML());
@@ -136,16 +152,23 @@ HTMLTableRowElement::Cells()
                                nullptr,
                                kNameSpaceID_XHTML,
                                false);
   }
 
   return mCells;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Cells());
+  return NS_OK;
+}
+
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableRowElement::InsertCell(int32_t aIndex,
                                 ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
@@ -183,16 +206,24 @@ HTMLTableRowElement::InsertCell(int32_t 
     return nullptr;
   }
 
   nsINode::InsertBefore(*cell, nextSibling, aError);
 
   return cell.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::InsertCell(int32_t aIndex, nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> cell = InsertCell(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(cell, aValue);
+}
+
 void
 HTMLTableRowElement::DeleteCell(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -215,16 +246,109 @@ HTMLTableRowElement::DeleteCell(int32_t 
   if (!cell) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*cell, aError);
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::DeleteCell(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteCell(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
 bool
 HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   /*
    * ignore these attributes, stored simply as strings
--- a/content/html/content/src/HTMLTableRowElement.h
+++ b/content/html/content/src/HTMLTableRowElement.h
@@ -2,27 +2,27 @@
 /* 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_HTMLTableRowElement_h
 #define mozilla_dom_HTMLTableRowElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableRowElement.h"
 
 class nsIDOMHTMLTableElement;
+class nsIDOMHTMLTableSectionElement;
 class nsContentList;
 
 namespace mozilla {
 namespace dom {
 
-class HTMLTableSectionElement;
-
 class HTMLTableRowElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLTableRowElement
 {
 public:
   HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)
@@ -34,16 +34,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableRowElement
+  NS_DECL_NSIDOMHTMLTABLEROWELEMENT
+
   int32_t RowIndex() const;
   int32_t SectionRowIndex() const;
   nsIHTMLCollection* Cells();
   already_AddRefed<nsGenericHTMLElement>
     InsertCell(int32_t aIndex, ErrorResult& aError);
   void DeleteCell(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
@@ -100,17 +103,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableRowElement,
                                                      nsGenericHTMLElement)
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  HTMLTableSectionElement* GetSection() const;
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection() const;
   HTMLTableElement* GetTable() const;
   nsRefPtr<nsContentList> mCells;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/content/html/content/src/HTMLTableSectionElement.cpp
+++ b/content/html/content/src/HTMLTableSectionElement.cpp
@@ -30,37 +30,115 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRows)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableSectionElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableSectionElement, Element)
 
 // QueryInterface implementation for HTMLTableSectionElement
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableSectionElement,
+                                nsIDOMHTMLTableSectionElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableSectionElement)
 
+NS_IMETHODIMP
+HTMLTableSectionElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableSectionElement::Rows()
 {
   if (!mRows) {
     mRows = new nsContentList(this,
                               mNodeInfo->NamespaceID(),
                               nsGkAtoms::tr,
                               nsGkAtoms::tr,
                               false);
   }
 
   return mRows;
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::GetRows(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Rows());
+  return NS_OK;
+}
+
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableSectionElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
@@ -89,16 +167,25 @@ HTMLTableSectionElement::InsertRow(int32
   if (doInsert) {
     nsINode::InsertBefore(*rowContent, rows->Item(aIndex), aError);
   } else {
     nsINode::AppendChild(*rowContent, aError);
   }
   return rowContent.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::InsertRow(int32_t aIndex,
+                                   nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> row = InsertRow(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(row, aValue);
+}
+
 void
 HTMLTableSectionElement::DeleteRow(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -121,16 +208,24 @@ HTMLTableSectionElement::DeleteRow(int32
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*row, aError);
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::DeleteRow(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteRow(aValue, rv);
+  return rv.ErrorCode();
+}
+
 bool
 HTMLTableSectionElement::ParseAttribute(int32_t aNamespaceID,
                                         nsIAtom* aAttribute,
                                         const nsAString& aValue,
                                         nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings
@@ -155,17 +250,17 @@ HTMLTableSectionElement::ParseAttribute(
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static
+static 
 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // height: value
     nsCSSValue* height = aData->ValueForHeight();
     if (height->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
@@ -194,17 +289,17 @@ void MapAttributesIntoRule(const nsMappe
   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
-    { &nsGkAtoms::align },
+    { &nsGkAtoms::align }, 
     { &nsGkAtoms::valign },
     { &nsGkAtoms::height },
     { nullptr }
   };
 
   static const MappedAttributeEntry* const map[] = {
     attributes,
     sCommonAttributeMap,
--- a/content/html/content/src/HTMLTableSectionElement.h
+++ b/content/html/content/src/HTMLTableSectionElement.h
@@ -2,23 +2,24 @@
 /* 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_HTMLTableSectionElement_h
 #define mozilla_dom_HTMLTableSectionElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsContentList.h" // For ctor.
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableSectionElement MOZ_FINAL : public nsGenericHTMLElement,
-                                          public nsIDOMHTMLElement
+                                          public nsIDOMHTMLTableSectionElement
 {
 public:
   HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   // nsISupports
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableSectionElement
+  NS_DECL_NSIDOMHTMLTABLESECTIONELEMENT
+
   nsIHTMLCollection* Rows();
   already_AddRefed<nsGenericHTMLElement>
     InsertRow(int32_t aIndex, ErrorResult& aError);
   void DeleteRow(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
   {
     GetHTMLAttr(nsGkAtoms::align, aAlign);
--- a/content/html/content/src/HTMLUnknownElement.cpp
+++ b/content/html/content/src/HTMLUnknownElement.cpp
@@ -1,15 +1,15 @@
 /* -*- 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 "nsDocument.h"
-#include "mozilla/dom/HTMLUnknownElement.h"
+#include "HTMLUnknownElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Unknown)
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ADDREF_INHERITED(HTMLUnknownElement, Element)
@@ -30,16 +30,19 @@ HTMLUnknownElement::WrapNode(JSContext *
       NS_ENSURE_TRUE(JS_WrapObject(aCx, prototype.address()), nullptr);
       NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
     }
   }
   return obj;
 }
 
 // QueryInterface implementation for HTMLUnknownElement
-NS_INTERFACE_MAP_BEGIN(HTMLUnknownElement)
+NS_INTERFACE_TABLE_HEAD(HTMLUnknownElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLUnknownElement,
+                                nsIDOMHTMLUnknownElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLUnknownElement)
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLUnknownElement.h
+++ b/content/html/content/src/HTMLUnknownElement.h
@@ -1,23 +1,24 @@
 /* -*- 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_HTMLUnknownElement_h
-#define mozilla_dom_HTMLUnknownElement_h
+#ifndef HTMLUnknownElement_h___
+#define HTMLUnknownElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLUnknownElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLUnknownElement MOZ_FINAL : public nsGenericHTMLElement
-                                   , public nsIDOMHTMLElement
+                                   , public nsIDOMHTMLUnknownElement
 {
 public:
   HTMLUnknownElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
     if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
       SetHasDirAuto();
     }
@@ -42,9 +43,9 @@ public:
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif /* mozilla_dom_HTMLUnknownElement_h */
+#endif /* HTMLUnknownElement_h___ */
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -239,19 +239,23 @@ for (var tag of allTags) {
   is(nodeString, "[object " + classInfoString,
      "Unexpected classname for " + tagName(tag));
   is(node instanceof window[classInfoString], true,
      tagName(tag) + " not an instance of " + classInfos[tag]);
 
   if (classInfoString != 'HTMLUnknownElement') {
     is(node instanceof HTMLUnknownElement, false,
        tagName(tag) + " is an instance of HTMLUnknownElement");
+    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, false,
+       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   } else {
     is(node instanceof HTMLUnknownElement, true,
        tagName(tag) + " is an instance of HTMLUnknownElement");
+    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, true,
+       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   }
 
   // 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);
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -206,47 +206,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocGlobalObject)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocGlobalObject)
 
-void
-XBL_ProtoErrorReporter(JSContext *cx,
-                       const char *message,
-                       JSErrorReport *report)
-{
-  // Make an nsIScriptError and populate it with information from
-  // this error.
-  nsCOMPtr<nsIScriptError>
-    errorObject(do_CreateInstance("@mozilla.org/scripterror;1"));
-  nsCOMPtr<nsIConsoleService>
-    consoleService(do_GetService("@mozilla.org/consoleservice;1"));
-
-  if (errorObject && consoleService) {
-    uint32_t column = report->uctokenptr - report->uclinebuf;
-
-    const PRUnichar* ucmessage =
-      static_cast<const PRUnichar*>(report->ucmessage);
-    const PRUnichar* uclinebuf =
-      static_cast<const PRUnichar*>(report->uclinebuf);
-
-    errorObject->Init
-         (ucmessage ? nsDependentString(ucmessage) : EmptyString(),
-          NS_ConvertUTF8toUTF16(report->filename),
-          uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
-          report->lineno, column, report->flags,
-          "xbl javascript"
-          );
-    consoleService->LogMessage(errorObject);
-  }
-}
-
 //----------------------------------------------------------------------
 //
 // nsIScriptGlobalObject methods
 //
 
 nsIScriptContext *
 nsXBLDocGlobalObject::GetScriptContext()
 {
@@ -275,20 +244,17 @@ nsXBLDocGlobalObject::EnsureScriptEnviro
   DebugOnly<nsresult> rv = newCtx->InitContext();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
   newCtx->DidInitializeContext();
 
   mScriptContext = newCtx;
 
   AutoPushJSContext cx(mScriptContext->GetNativeContext());
 
-  // nsJSEnvironment set the error reporter to NS_ScriptErrorReporter so
-  // we must apparently override that with our own (although it isn't clear 
-  // why - see bug 339647)
-  JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
+  JS_SetErrorReporter(cx, xpc::SystemErrorReporter);
 
   JS::CompartmentOptions options;
   options.setZone(JS::SystemZone);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
                                  options);
   if (!mJSObject)
       return NS_OK;
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/898906.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+
+var plug = navigator.plugins[0];
+var mime = plug[0];
+// This shouldn't leak.
+mime.expando = true;
+
+</script>
+</head>
+</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -35,9 +35,10 @@ load 693811-1.html
 load 693811-2.html
 load 693811-3.html
 load 695867.html
 load 697643.html
 load 706283-1.html
 load 708405-1.html
 load 745495.html
 load 844559.html
-load 886213.html
\ No newline at end of file
+load 886213.html
+load 898906.html
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3690,16 +3690,21 @@ OldBindingConstructorEnabled(const nsGlo
 
   // Don't expose CSSSupportsRule unless @supports processing is enabled.
   if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
     if (!CSSSupportsRule::PrefEnabled()) {
       return false;
     }
   }
 
+  // Don't expose CSSFontFeatureValuesRule unless the pref is enabled
+  if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
+    return nsCSSFontFeatureValuesRule::PrefEnabled();
+  }
+
   return true;
 }
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                           bool *did_resolve)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -15,16 +15,17 @@
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLMapElement.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
 #include "nsIContentViewer.h"
--- a/dom/base/nsMimeTypeArray.cpp
+++ b/dom/base/nsMimeTypeArray.cpp
@@ -214,17 +214,17 @@ nsMimeTypeArray::EnsureMimeTypes()
   }
 
   mPluginMimeTypeCount = mMimeTypes.Length();
 }
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsMimeType, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release)
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsMimeType)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsMimeType, mPluginElement)
 
 nsMimeType::nsMimeType(nsWeakPtr aWindow, nsPluginElement* aPluginElement,
                        uint32_t aPluginTagMimeIndex, const nsAString& aType)
   : mWindow(aWindow),
     mPluginElement(aPluginElement),
     mPluginTagMimeIndex(aPluginTagMimeIndex),
     mType(aType)
 {
--- a/dom/base/nsMimeTypeArray.h
+++ b/dom/base/nsMimeTypeArray.h
@@ -7,19 +7,19 @@
 #ifndef nsMimeTypeArray_h___
 #define nsMimeTypeArray_h___
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
 #include "nsWrapperCache.h"
+#include "nsPluginArray.h"
 
 class nsPIDOMWindow;
-class nsPluginElement;
 class nsMimeType;
 
 class nsMimeTypeArray MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
 public:
   nsMimeTypeArray(nsWeakPtr aWindow);
   virtual ~nsMimeTypeArray();
@@ -68,34 +68,32 @@ public:
              uint32_t aPluginTagMimeIndex, const nsAString& aMimeType);
   nsMimeType(nsWeakPtr aWindow, const nsAString& aMimeType);
   virtual ~nsMimeType();
 
   nsPIDOMWindow* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  void Invalidate()
-  {
-    mPluginElement = nullptr;
-  }
-
   const nsString& Type() const
   {
     return mType;
   }
 
   // MimeType WebIDL methods
   void GetDescription(nsString& retval) const;
   nsPluginElement *GetEnabledPlugin() const;
   void GetSuffixes(nsString& retval) const;
   void GetType(nsString& retval) const;
 
 protected:
   nsWeakPtr mWindow;
 
-  // Weak pointer to the active plugin, if any.
-  nsPluginElement *mPluginElement;
+  // Strong reference to the active plugin, if any. Note that this
+  // creates an explicit reference cycle through the plugin element's
+  // mimetype array. We rely on the cycle collector to break this
+  // cycle.
+  nsRefPtr<nsPluginElement> mPluginElement;
   uint32_t mPluginTagMimeIndex;
   nsString mType;
 };
 
 #endif /* nsMimeTypeArray_h___ */
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -277,40 +277,26 @@ nsPluginArray::EnsurePlugins()
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginElement)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginElement)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginElement)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPluginElement)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-  // Invalidate before we unlink mMimeTypes
-  tmp->Invalidate();
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMimeTypes)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPluginElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsPluginElement)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPluginElement, mMimeTypes)
 
 nsPluginElement::nsPluginElement(nsWeakPtr aWindow,
                                  nsPluginTag* aPluginTag)
   : mWindow(aWindow),
     mPluginTag(aPluginTag)
 {
   SetIsDOMBinding();
 }
 
-nsPluginElement::~nsPluginElement()
-{
-  Invalidate();
-}
-
 nsPIDOMWindow*
 nsPluginElement::GetParentObject() const
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
   MOZ_ASSERT(win);
   return win;
 }
 
@@ -420,16 +406,8 @@ nsPluginElement::EnsureMimeTypes()
     return;
   }
 
   for (uint32_t i = 0; i < mPluginTag->mMimeTypes.Length(); ++i) {
     NS_ConvertUTF8toUTF16 type(mPluginTag->mMimeTypes[i]);
     mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type));
   }
 }
-
-void
-nsPluginElement::Invalidate()
-{
-  for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
-    mMimeTypes[i]->Invalidate();
-  }
-}
--- a/dom/base/nsPluginArray.h
+++ b/dom/base/nsPluginArray.h
@@ -69,17 +69,16 @@ private:
 class nsPluginElement MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPluginElement)
 
   nsPluginElement(nsWeakPtr aWindow, nsPluginTag* aPluginTag);
-  virtual ~nsPluginElement();
 
   nsPIDOMWindow* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsPluginTag* PluginTag() const
   {
     return mPluginTag;
@@ -97,16 +96,15 @@ public:
   nsMimeType* NamedGetter(const nsAString& name, bool &found);
   uint32_t Length();
   void GetSupportedNames(nsTArray< nsString >& retval);
 
   nsTArray<nsRefPtr<nsMimeType> >& MimeTypes();
 
 protected:
   void EnsureMimeTypes();
-  void Invalidate();
 
   nsWeakPtr mWindow;
   nsRefPtr<nsPluginTag> mPluginTag;
   nsTArray<nsRefPtr<nsMimeType> > mMimeTypes;
 };
 
 #endif /* nsPluginArray_h___ */
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1665,18 +1665,21 @@ class CGCreateInterfaceObjectsMethod(CGA
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'aGlobal'),
                 Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
         CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
         self.properties = properties
     def definition_body(self):
         protoChain = self.descriptor.prototypeChain
         if len(protoChain) == 1:
-            getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
             parentProtoType = "Rooted"
+            if self.descriptor.interface.getExtendedAttribute("ArrayClass"):
+                getParentProto = "aCx, JS_GetArrayPrototype(aCx, aGlobal)"
+            else:
+                getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
         else:
             parentProtoName = self.descriptor.prototypeChain[-2]
             getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
                               toBindingNamespace(parentProtoName))
             parentProtoType = "Handle"
 
         parentWithInterfaceObject = self.descriptor.interface.parent
         while (parentWithInterfaceObject and
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -908,26 +908,40 @@ class IDLInterface(IDLObjectWithScope):
                     # whether the result is actually one of our existing
                     # NamedConstructors.
                     newMethod = self.parentScope.lookupIdentifier(method.identifier)
                     if newMethod == method:
                         self.namedConstructors.append(method)
                     elif not newMethod in self.namedConstructors:
                         raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
                                           [method.location, newMethod.location])
+            elif (identifier == "ArrayClass"):
+                if not attr.noArguments():
+                    raise WebIDLError("[ArrayClass] must take no arguments",
+                                      [attr.location])
+                if self.parent:
+                    raise WebIDLError("[ArrayClass] must not be specified on "
+                                      "an interface with inherited interfaces",
+                                      [attr.location, self.location])
             elif (identifier == "PrefControlled" or
-                  identifier == "Pref" or
                   identifier == "NeedNewResolve" or
+                  identifier == "OverrideBuiltins" or
+                  identifier == "ChromeOnly"):
+                # Known extended attributes that do not take values
+                if not attr.noArguments():
+                    raise WebIDLError("[%s] must take no arguments" % identifier,
+                                      [attr.location])
+            elif (identifier == "Pref" or
                   identifier == "JSImplementation" or
                   identifier == "HeaderFile" or
-                  identifier == "NavigatorProperty" or
-                  identifier == "OverrideBuiltins" or
-                  identifier == "ChromeOnly"):
-                # Known attributes that we don't need to do anything with here
-                pass
+                  identifier == "NavigatorProperty"):
+                # Known extended attributes that take a string value
+                if not attr.hasValue():
+                    raise WebIDLError("[%s] must have a value" % identifier,
+                                      [attr.location])
             else:
                 raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
                                   [attr.location])
 
             attrlist = attr.listValue()
             self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
 
     def addImplementedInterface(self, implementedInterface):
--- a/dom/bindings/parser/tests/test_interface.py
+++ b/dom/bindings/parser/tests/test_interface.py
@@ -369,8 +369,37 @@ def WebIDLTest(parser, harness):
                 readonly attribute boolean y;
             };
         """)
         results = parser.finish()
     except:
         threw = True
     harness.ok(threw,
                "Should not allow unknown extended attributes on interfaces")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface B {};
+            [ArrayClass]
+            interface A : B {
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(threw,
+               "Should not allow [ArrayClass] on interfaces with parents")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            [ArrayClass]
+            interface A {
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(not threw,
+               "Should allow [ArrayClass] on interfaces without parents")
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -68,16 +68,17 @@ interface nsIDOMMozCSSKeyframeRule;
 interface nsIDOMCSSFontFeatureValuesRule;
 interface nsIDOMCSSStyleSheet;
 interface nsIDOMCSSStyleDeclaration;
 interface nsIDOMCounter;
 interface nsIDOMRect;
 interface nsIDOMCSSStyleRule;
 interface nsIDOMCSSStyleRuleCollection;
 interface nsIDOMHTMLTableCaptionElement;
+interface nsIDOMHTMLTableSectionElement;
 
 // Range
 interface nsIDOMRange;
 
 // Crypto
 interface nsIDOMCRMFObject;
 interface nsIDOMCrypto;
 interface nsIDOMPkcs11;
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -11,55 +11,71 @@ XPIDL_SOURCES += [
     'nsIDOMHTMLAudioElement.idl',
     'nsIDOMHTMLBRElement.idl',
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLBodyElement.idl',
     'nsIDOMHTMLButtonElement.idl',
     'nsIDOMHTMLByteRanges.idl',
     'nsIDOMHTMLCanvasElement.idl',
     'nsIDOMHTMLCollection.idl',
+    'nsIDOMHTMLDListElement.idl',
+    'nsIDOMHTMLDataListElement.idl',
     'nsIDOMHTMLDirectoryElement.idl',
     'nsIDOMHTMLDivElement.idl',
     'nsIDOMHTMLDocument.idl',
     'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLEmbedElement.idl',
     'nsIDOMHTMLFieldSetElement.idl',
+    'nsIDOMHTMLFontElement.idl',
     'nsIDOMHTMLFormElement.idl',
     'nsIDOMHTMLFrameElement.idl',
     'nsIDOMHTMLFrameSetElement.idl',
     'nsIDOMHTMLHRElement.idl',
     'nsIDOMHTMLHeadElement.idl',
+    'nsIDOMHTMLHeadingElement.idl',
     'nsIDOMHTMLHtmlElement.idl',
     'nsIDOMHTMLIFrameElement.idl',
     'nsIDOMHTMLImageElement.idl',
     'nsIDOMHTMLInputElement.idl',
     'nsIDOMHTMLLIElement.idl',
+    'nsIDOMHTMLLabelElement.idl',
+    'nsIDOMHTMLLegendElement.idl',
     'nsIDOMHTMLLinkElement.idl',
     'nsIDOMHTMLMapElement.idl',
     'nsIDOMHTMLMediaElement.idl',
     'nsIDOMHTMLMenuElement.idl',
     'nsIDOMHTMLMenuItemElement.idl',
     'nsIDOMHTMLMetaElement.idl',
+    'nsIDOMHTMLMeterElement.idl',
+    'nsIDOMHTMLModElement.idl',
     'nsIDOMHTMLOListElement.idl',
     'nsIDOMHTMLObjectElement.idl',
     'nsIDOMHTMLOptGroupElement.idl',
     'nsIDOMHTMLOptionElement.idl',
     'nsIDOMHTMLOptionsCollection.idl',
+    'nsIDOMHTMLOutputElement.idl',
     'nsIDOMHTMLParagraphElement.idl',
+    'nsIDOMHTMLParamElement.idl',
     'nsIDOMHTMLPreElement.idl',
+    'nsIDOMHTMLProgressElement.idl',
     'nsIDOMHTMLQuoteElement.idl',
     'nsIDOMHTMLScriptElement.idl',
     'nsIDOMHTMLSelectElement.idl',
     'nsIDOMHTMLSourceElement.idl',
     'nsIDOMHTMLStyleElement.idl',
     'nsIDOMHTMLTableCaptionElem.idl',
+    'nsIDOMHTMLTableCellElement.idl',
+    'nsIDOMHTMLTableColElement.idl',
     'nsIDOMHTMLTableElement.idl',
+    'nsIDOMHTMLTableRowElement.idl',
+    'nsIDOMHTMLTableSectionElement.idl',
     'nsIDOMHTMLTextAreaElement.idl',
     'nsIDOMHTMLTitleElement.idl',
     'nsIDOMHTMLUListElement.idl',
+    'nsIDOMHTMLUnknownElement.idl',
     'nsIDOMHTMLVideoElement.idl',
     'nsIDOMMediaError.idl',
     'nsIDOMMozBrowserFrame.idl',
     'nsIDOMTimeRanges.idl',
     'nsIDOMValidityState.idl',
     'nsIMozBrowserFrame.idl',
 ]
 
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLDListElement.idl
@@ -0,0 +1,23 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLDListElement interface is the interface to a [X]HTML
+ * dl element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(edd9338b-f0d5-4825-97d6-6a49862309cc)]
+interface nsIDOMHTMLDListElement : nsIDOMHTMLElement
+{
+           attribute boolean          compact;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl
@@ -0,0 +1,25 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLDataListElement interface is the interface to a HTML
+ * <datalist> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-datalist-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+interface nsIDOMHTMLCollection;
+
+[scriptable, uuid(528e6a6b-f957-42e1-8d1b-eeeb2fd0b128)]
+interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLCollection options;
+};
+
--- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
@@ -11,13 +11,13 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-// Exists so that | element instanceof Ci.nsIDOMHTMLDirectoryElement | works.
 [scriptable, uuid(cf50373e-e004-4cec-bc65-be9250d9e4c8)]
 interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement
 {
+           attribute boolean          compact;
 };
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLFontElement.idl
@@ -0,0 +1,25 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLFontElement interface is the interface to a [X]HTML
+ * font element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(e4d86aad-f245-4901-877e-0ae233c5fd37)]
+interface nsIDOMHTMLFontElement : nsIDOMHTMLElement
+{
+           attribute DOMString        color;
+           attribute DOMString        face;
+           attribute DOMString        size;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl
@@ -0,0 +1,23 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLHeadingElement interface is the interface to a
+ * [X]HTML h1, h2, h3, ... element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(e601aadf-e9e7-4605-a6f9-2cd2006723de)]
+interface nsIDOMHTMLHeadingElement : nsIDOMHTMLElement
+{
+           attribute DOMString        align;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl
@@ -0,0 +1,25 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLLabelElement interface is the interface to a [X]HTML
+ * label element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(cbffa708-f51e-4c74-9644-19f9d417aac5)]
+interface nsIDOMHTMLLabelElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLFormElement form;
+           attribute DOMString             htmlFor;
+  readonly attribute nsIDOMHTMLElement     control;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl
@@ -0,0 +1,24 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLLegendElement interface is the interface to a [X]HTML
+ * legend element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(2e4567be-3d91-4df8-bdf9-f3bd96a6cd06)]
+interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLFormElement form;
+           attribute DOMString             align;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLMeterElement.idl
@@ -0,0 +1,30 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLMeterElement interface is the interface to a HTML
+ * <meter> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-meter-element
+ */
+
+[scriptable, uuid(6b1fc313-a7c1-4064-ba24-b72e099b05fa)]
+interface nsIDOMHTMLMeterElement : nsIDOMHTMLElement
+{
+           attribute double value;
+           attribute double min;
+           attribute double max;
+           attribute double low;
+           attribute double high;
+           attribute double optimum;
+
+  /**
+   * The labels attribute will be done with bug 556743.
+   */
+  //readonly attribute NodeList labels;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLModElement.idl
@@ -0,0 +1,24 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLModElement interface is the interface to a [X]HTML
+ * ins and del element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(8a1bdf64-19f3-401b-aaea-8c6a5ef1c66f)]
+interface nsIDOMHTMLModElement : nsIDOMHTMLElement
+{
+           attribute DOMString        cite;
+           attribute DOMString        dateTime;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl
@@ -0,0 +1,43 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLOutputElement interface is the interface to a HTML
+ * <output> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+interface nsIDOMValidityState;
+
+[scriptable, uuid(c4bff576-90b5-44b0-8278-bf4e3010b09a)]
+interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement
+{
+  // DOMSettableTokenList
+  readonly attribute nsISupports                htmlFor;
+  readonly attribute nsIDOMHTMLFormElement      form;
+           attribute DOMString                  name;
+
+  readonly attribute DOMString                  type;
+           attribute DOMString                  defaultValue;
+           attribute DOMString                  value;
+
+  readonly attribute boolean                    willValidate;
+  readonly attribute nsIDOMValidityState        validity;
+  readonly attribute DOMString                  validationMessage;
+  boolean  checkValidity();
+  void     setCustomValidity(in DOMString error);
+
+  /**
+   * The labels IDL attribute will be added with bug 556743.
+   */
+  //readonly attribute nsIDOMNodeList             labels;
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLParamElement.idl
@@ -0,0 +1,26 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLParamElement interface is the interface to a [X]HTML
+ * param element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(f85e1b05-6dc4-442d-bea8-7cf551f9bc9f)]
+interface nsIDOMHTMLParamElement : nsIDOMHTMLElement
+{
+           attribute DOMString        name;
+           attribute DOMString        type;
+           attribute DOMString        value;
+           attribute DOMString        valueType;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl
@@ -0,0 +1,29 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLProgressElement interface is the interface to a HTML
+ * <progress> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-progress-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+[scriptable, uuid(4b4bec16-c65f-4a08-97d1-dff624efdca4)]
+interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement
+{
+           attribute double value;
+           attribute double max;
+  readonly attribute double position;
+  /**
+   * The labels attribute will be done with bug 567740.
+   */
+  //readonly attribute NodeList labels;
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl
@@ -0,0 +1,37 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableCellElement interface is the interface to a
+ * [X]HTML td element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(1fb22137-c231-4eae-9ca4-557bb0852d89)]
+interface nsIDOMHTMLTableCellElement : nsIDOMHTMLElement
+{
+  readonly attribute long             cellIndex;
+           attribute DOMString        abbr;
+           attribute DOMString        align;
+           attribute DOMString        axis;
+           attribute DOMString        bgColor;
+           attribute DOMString        ch;
+           attribute DOMString        chOff;
+           attribute long             colSpan;
+           attribute DOMString        headers;
+           attribute DOMString        height;
+           attribute boolean          noWrap;
+           attribute long             rowSpan;
+           attribute DOMString        scope;
+           attribute DOMString        vAlign;
+           attribute DOMString        width;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl
@@ -0,0 +1,28 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableColElement interface is the interface to a
+ * [X]HTML col element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(cd5a5a33-7101-4d32-987c-337c004fce1a)]
+interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement
+{
+           attribute DOMString        align;
+           attribute DOMString        ch;
+           attribute DOMString        chOff;
+           attribute long             span;
+           attribute DOMString        vAlign;
+           attribute DOMString        width;
+};
--- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl
@@ -14,9 +14,44 @@
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 [scriptable, uuid(1a7bf1f1-5d6c-4200-9ceb-455874322315)]
 interface nsIDOMHTMLTableElement : nsIDOMHTMLElement
 {
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableCaptionElement caption;
+                                             // raises(DOMException) on setting
+
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableSectionElement tHead;
+                                             // raises(DOMException) on setting
+
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableSectionElement tFoot;
+                                             // raises(DOMException) on setting
+
+  readonly attribute nsIDOMHTMLCollection          rows;
+  readonly attribute nsIDOMHTMLCollection          tBodies;
+           attribute DOMString                     align;
+           attribute DOMString                     bgColor;
+           attribute DOMString                     border;
+           attribute DOMString                     cellPadding;
+           attribute DOMString                     cellSpacing;
+           attribute DOMString                     frame;
+           attribute DOMString                     rules;
+           attribute DOMString                     summary;
+           attribute DOMString                     width;
+  nsIDOMHTMLElement         createTHead();
+  void                      deleteTHead();
+  nsIDOMHTMLElement         createTFoot();
+  void                      deleteTFoot();
+  nsIDOMHTMLElement         createCaption();
+  void                      deleteCaption();
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertRow(in long index)
+                                             raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteRow(in long index)
+                                             raises(DOMException);
 };
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl
@@ -0,0 +1,39 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableRowElement interface is the interface to a
+ * [X]HTML tr element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(02094366-0d3d-47e3-949c-89113a9bcc15)]
+interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement
+{
+  // Modified in DOM Level 2:
+  readonly attribute long                 rowIndex;
+  // Modified in DOM Level 2:
+  readonly attribute long                 sectionRowIndex;
+  // Modified in DOM Level 2:
+  readonly attribute nsIDOMHTMLCollection cells;
+           attribute DOMString            align;
+           attribute DOMString            bgColor;
+           attribute DOMString            ch;
+           attribute DOMString            chOff;
+           attribute DOMString            vAlign;
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertCell(in long index)
+                                               raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteCell(in long index)
+                                               raises(DOMException);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableSectionElement.idl
@@ -0,0 +1,33 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableSectionElement interface is the interface to a
+ * [X]HTML thead, tbody, and tfoot element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, builtinclass, uuid(7b91cf4c-5194-4122-bc29-7bbd18ba0020)]
+interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement
+{
+           attribute DOMString            align;
+           attribute DOMString            ch;
+           attribute DOMString            chOff;
+           attribute DOMString            vAlign;
+  readonly attribute nsIDOMHTMLCollection rows;
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertRow(in long index)
+                                               raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteRow(in long index)
+                                               raises(DOMException);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl
@@ -0,0 +1,17 @@
+/* -*- 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLUnknownElement interface is the interface to an unknown HTML
+ * element.
+ *
+ * @see <http://www.whatwg.org/html/#htmlunknownelement>
+ */
+[scriptable, uuid(aa044a2d-4e9b-4fc5-8ad2-666da9062b36)]
+interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement
+{
+};
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -169,16 +169,17 @@ InternalSetAudioRoutes(SwitchState aStat
   }
 }
 
 void
 AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
                                            const char* aTopic,
                                            const nsCString aAddress)
 {
+#ifdef MOZ_B2G_BT
   bool status;
   if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
     BluetoothHfpManager* hfp =
       static_cast<BluetoothHfpManager*>(aSubject);
     status = hfp->IsScoConnected();
   } else {
     BluetoothProfileManagerBase* profile =
       static_cast<BluetoothProfileManagerBase*>(aSubject);
@@ -216,16 +217,17 @@ AudioManager::HandleBluetoothStatusChang
       AudioSystem::setParameters(0, cmd);
     }
   } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
     AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
                                           audioState, aAddress.get());
     AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
                                           audioState, aAddress.get());
   }
+#endif
 }
 
 nsresult
 AudioManager::Observe(nsISupports* aSubject,
                       const char* aTopic,
                       const PRUnichar* aData)
 {
   if ((strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID) == 0) ||
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -355,34 +355,34 @@ CallBarringOption.prototype = {
                       password: 'r',
                       serviceClass: 'r'}
 };
 
 function DOMMMIResult(result) {
   this.serviceCode = result.serviceCode;
   this.statusMessage = result.statusMessage;
   this.additionalInformation = result.additionalInformation;
-};
+}
 DOMMMIResult.prototype = {
   __exposedProps__: {serviceCode: 'r',
                      statusMessage: 'r',
                      additionalInformation: 'r'}
 };
 
 function DOMCLIRStatus(option) {
   this.n = option.n;
   this.m = option.m;
-};
+}
 DOMCLIRStatus.prototype = {
   __exposedProps__ : {n: 'r',
                       m: 'r'}
 };
 
 function DOMMMIError() {
-};
+}
 DOMMMIError.prototype = {
   classDescription: "DOMMMIError",
   classID:          DOMMMIERROR_CID,
   contractID:       "@mozilla.org/dom/mmi-error;1",
   QueryInterface:   XPCOMUtils.generateQI([Ci.nsISupports]),
   __init: function(serviceCode,
                    name,
                    message,
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -32,17 +32,17 @@ try {
   debugPref = Services.prefs.getBoolPref("ril.debugging.enabled");
 } catch(e) {
   debugPref = false;
 }
 DEBUG = RIL.DEBUG_RIL || debugPref;
 
 function debug(s) {
   dump("-*- RadioInterfaceLayer: " + s + "\n");
-};
+}
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
 const RADIOINTERFACE_CID =
   Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
 const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
 
@@ -61,16 +61,17 @@ const kMozSettingsChangedObserverTopic  
 const kSysMsgListenerReadyObserverTopic  = "system-message-listener-ready";
 const kSysClockChangeObserverTopic       = "system-clock-change";
 const kScreenStateChangedTopic           = "screen-state-changed";
 const kTimeNitzAutomaticUpdateEnabled    = "time.nitz.automatic-update.enabled";
 const kTimeNitzAvailable                 = "time.nitz.available";
 const kCellBroadcastSearchList           = "ril.cellbroadcast.searchlist";
 const kCellBroadcastDisabled             = "ril.cellbroadcast.disabled";
 const kPrefenceChangedObserverTopic      = "nsPref:changed";
+const kClirModePreference                = "ril.clirMode";
 
 const DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED = "received";
 const DOM_MOBILE_MESSAGE_DELIVERY_SENDING  = "sending";
 const DOM_MOBILE_MESSAGE_DELIVERY_SENT     = "sent";
 const DOM_MOBILE_MESSAGE_DELIVERY_ERROR    = "error";
 
 const CALL_WAKELOCK_TIMEOUT              = 5000;
 
@@ -557,24 +558,29 @@ XPCOMUtils.defineLazyGetter(this, "gMess
   };
 });
 
 function RadioInterfaceLayer() {
   gMessageManager.init(this);
 
   let options = {
     debug: debugPref,
-    cellBroadcastDisabled: false
+    cellBroadcastDisabled: false,
+    clirMode: RIL.CLIR_DEFAULT
   };
 
   try {
     options.cellBroadcastDisabled =
       Services.prefs.getBoolPref(kCellBroadcastDisabled);
   } catch(e) {}
 
+  try {
+    options.clirMode = Services.prefs.getIntPref(kClirModePreference);
+  } catch(e) {}
+
   let numIfaces = this.numRadioInterfaces;
   debug(numIfaces + " interfaces");
   this.radioInterfaces = [];
   for (let clientId = 0; clientId < numIfaces; clientId++) {
     options.clientId = clientId;
     this.radioInterfaces.push(new RadioInterface(options));
   }
 }
@@ -2333,18 +2339,33 @@ RadioInterface.prototype = {
   handleGetCLIR: function handleGetCLIR(message) {
     if (DEBUG) this.debug("handleGetCLIR: " + JSON.stringify(message));
     gMessageManager.sendRequestResults("RIL:GetCallingLineIdRestriction",
                                        message);
   },
 
   handleSetCLIR: function handleSetCLIR(message) {
     if (DEBUG) this.debug("handleSetCLIR: " + JSON.stringify(message));
-    gMessageManager.sendRequestResults("RIL:SetCallingLineIdRestriction",
-                                       message);
+    let messageType;
+    if (message.isSendMMI) {
+      messageType = message.success ? "RIL:SendMMI:Return:OK" :
+                                      "RIL:SendMMI:Return:KO";
+    } else {
+      messageType = "RIL:SetCallingLineIdRestriction";
+    }
+    if (message.success) {
+      try {
+        Services.prefs.setIntPref(kClirModePreference, message.clirMode);
+        Services.prefs.savePrefFile(null);
+        if (DEBUG) {
+          this.debug(kClirModePreference + " pref is now " + message.clirMode);
+        }
+      } catch (e) {}
+    }
+    gMessageManager.sendRequestResults(messageType, message);
   },
 
   handleSetRoamingPreference: function handleSetRoamingPreference(message) {
     if (DEBUG) this.debug("handleSetRoamingPreference: " + JSON.stringify(message));
     gMessageManager.sendRequestResults("RIL:SetRoamingPreference", message);
   },
 
   handleQueryRoamingPreference: function handleQueryRoamingPreference(message) {
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -756,16 +756,21 @@ let RIL = {
   preferredNetworkType: null,
 
   /**
    * Global Cell Broadcast switch.
    */
   cellBroadcastDisabled: false,
 
   /**
+   * Global CLIR mode settings.
+   */
+  clirMode: CLIR_DEFAULT,
+
+  /**
    * Parsed Cell Broadcast search lists.
    * cellBroadcastConfigs.MMI should be preserved over rild reset.
    */
   cellBroadcastConfigs: null,
   mergedCellBroadcastConfig: null,
 
   _receivedSmsCbPagesMap: {},
 
@@ -1496,19 +1501,22 @@ let RIL = {
    * Enables or disables the presentation of the calling line identity (CLI) to
    * the called party when originating a call.
    *
    * @param options.clirMode
    *        Is one of the CLIR_* constants in
    *        nsIDOMMozMobileConnection interface.
    */
   setCLIR: function setCLIR(options) {
+    if (options) {
+      this.clirMode = options.clirMode;
+    }
     Buf.newParcel(REQUEST_SET_CLIR, options);
     Buf.writeUint32(1);
-    Buf.writeUint32(options.clirMode);
+    Buf.writeUint32(this.clirMode);
     Buf.sendParcel();
   },
 
   /**
    * Set screen state.
    *
    * @param on
    *        Boolean indicating whether the screen should be on or off.
@@ -2543,16 +2551,18 @@ let RIL = {
             break;
           case MMI_PROCEDURE_DEACTIVATION:
             options.clirMode = CLIR_SUPPRESSION;
             break;
           default:
             _sendMMIError(MMI_ERROR_KS_NOT_SUPPORTED, MMI_KS_SC_CLIR);
             return;
         }
+        options.rilMessageType = "setCLIR";
+        options.isSendMMI = true;
         this.setCLIR(options);
         return;
 
       // Call barring
       case MMI_SC_BAOC:
       case MMI_SC_BAOIC:
       case MMI_SC_BAOICxH:
       case MMI_SC_BAIC:
@@ -3291,17 +3301,17 @@ let RIL = {
       } else {
         if (mmiServiceCode === MMI_KS_SC_PIN ||
             mmiServiceCode === MMI_KS_SC_PIN2) {
           options.errorMsg = MMI_ERROR_KS_BAD_PIN;
         } else if (mmiServiceCode === MMI_KS_SC_PUK ||
                    mmiServiceCode === MMI_KS_SC_PUK2) {
           options.errorMsg = MMI_ERROR_KS_BAD_PUK;
         }
-        if (options.retryCount != undefined) {
+        if (options.retryCount !== undefined) {
           options.additionalInformation = options.retryCount;
         }
       }
     }
 
     this.sendChromeMessage(options);
   },
 
@@ -4658,16 +4668,17 @@ let RIL = {
       method.call(this, length, options);
     }
   },
 
   setInitialOptions: function setInitialOptions(options) {
     DEBUG = DEBUG_WORKER || options.debug;
     CLIENT_ID = options.clientId;
     this.cellBroadcastDisabled = options.cellBroadcastDisabled;
+    this.clirMode = options.clirMode;
   }
 };
 
 RIL.initRILState();
 
 RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
   if (options.rilRequestError) {
     return;
@@ -5159,21 +5170,25 @@ RIL[REQUEST_GET_CLIR] = function REQUEST
         options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
         break;
     }
   }
 
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
+  if (options.rilMessageType == null) {
+    // The request was made by ril_worker itself automatically. Don't report.
+    return;
+  }
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
-  if (options.success && (options.rilMessageType === "sendMMI")) {
+  if (options.success && options.isSendMMI) {
     switch (options.procedure) {
       case MMI_PROCEDURE_ACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_ENABLED;
         break;
       case MMI_PROCEDURE_DEACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
         break;
     }
@@ -5326,17 +5341,17 @@ RIL[REQUEST_QUERY_FACILITY_LOCK] = funct
     if (!options.enabled) {
       options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
     } else {
       options.statusMessage = MMI_SM_KS_SERVICE_ENABLED_FOR;
       let serviceClass = [];
       for (let serviceClassMask = 1;
            serviceClassMask <= ICC_SERVICE_CLASS_MAX;
            serviceClassMask <<= 1) {
-        if ((serviceClassMask & services) != 0) {
+        if ((serviceClassMask & services) !== 0) {
           serviceClass.push(MMI_KS_SERVICE_CLASS_MAPPING[serviceClassMask]);
         }
       }
 
       options.additionalInformation = serviceClass;
     }
   }
   this.sendChromeMessage(options);
@@ -5820,16 +5835,17 @@ RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHA
       } else {
         this.getIMEI();
         this.getIMEISV();
       }
     }
     this.getBasebandVersion();
     this.updateCellBroadcastConfig();
     this.setPreferredNetworkType();
+    this.setCLIR();
   }
 
   this.radioState = newState;
   this.sendChromeMessage({
     rilMessageType: "radiostatechange",
     radioState: newState
   });
 
@@ -10969,30 +10985,26 @@ let ICCRecordHelper = {
         pbrTlvs.push({tag: tag,
                       length: tlvLen,
                       value: tlvs});
 
         readLen += tlvLen + 2; // +2 for tag and tlvLen
       }
       Buf.readStringDelimiter(strLen);
 
-      if (pbrTlvs.length === 0) {
-        let error = onerror || debug;
-        error("Cannot access Phonebook.");
-        return;
-      }
-
-      let pbr = ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
-      // EF_ADN is mandatory if and only if DF_PHONEBOOK is present.
-      if (!pbr.adn) {
-        let error = onerror || debug;
-        error("Cannot access ADN.");
-        return;
-      }
-      pbrs.push(pbr);
+      if (pbrTlvs.length > 0) {
+        let pbr = ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
+        // EF_ADN is mandatory if and only if DF_PHONEBOOK is present.
+        if (!pbr.adn) {
+          let error = onerror || debug;
+          error("Cannot access ADN.");
+          return;
+        }
+        pbrs.push(pbr);
+      }
 
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
         if (onsuccess) {
           onsuccess(pbrs);
         }
       }
@@ -12027,17 +12039,17 @@ let ICCUtilsHelper = {
    * @param mncLength [optional]
    *        The length of mnc.
    *
    * @return An object contains the parsing result of mcc and mnc.
    *         Or null if any error occurred.
    */
   parseMccMncFromImsi: function parseMccMncFromImsi(imsi, mncLength) {
     if (!imsi) {
-      return;
+      return null;
     }
 
     // MCC is the first 3 digits of IMSI.
     let mcc = imsi.substr(0,3);
     if (!mncLength) {
       // Check the MCC table to decide the length of MNC.
       let index = MCC_TABLE_FOR_MNC_LENGTH_IS_3.indexOf(mcc);
       mncLength = (index !== -1) ? 3 : 2;
@@ -12409,16 +12421,21 @@ let ICCContactHelper = {
    * @param contact       The contact will be updated.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateUSimContact: function updateUSimContact(contact, onsuccess, onerror) {
     let gotPbrCb = function gotPbrCb(pbrs) {
       let pbrIndex = Math.floor(contact.recordId / ICC_MAX_LINEAR_FIXED_RECORDS);
       let pbr = pbrs[pbrIndex];
+      if (!pbr) {
+        let error = onerror || debug;
+        error("Cannot access Phonebook.");
+        return;
+      }
       this.updatePhonebookSet(pbr, contact, onsuccess, onerror);
     }.bind(this);
 
     ICCRecordHelper.readPBR(gotPbrCb, onerror);
   },
 
   /**
    * Update fields in Phonebook Reference File.
--- a/dom/system/gonk/tests/marionette/manifest.ini
+++ b/dom/system/gonk/tests/marionette/manifest.ini
@@ -2,8 +2,9 @@
 b2g = true
 browser = false
 qemu = true
 
 [test_geolocation.js]
 disabled = Bug 808783
 [test_get_voicemailInfo.js]
 [test_fakevolume.js]
+[test_ril_code_quality.py]
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/marionette/ril_jshint/README.md
@@ -0,0 +1,9 @@
+Test RIL Code Quality
+=====================
+
+For more information, please refer to
+
+* Bug 880643 - B2G RIL: Add a code quality test on try server for RIL javascript code in gecko
+* Slide: https://speakerdeck.com/aknow/improve-code-quality-of-ril-code-by-jshint
+* Document: https://hackpad.com/Code-Quality-Test-For-RIL-Javascript-Code-In-Gecko-cz5j7YIGiw8
+
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/marionette/ril_jshint/jshint.js
@@ -0,0 +1,11096 @@
+//2.1.3
+var JSHINT;
+(function () {
+var require;
+require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+
+process.nextTick = (function () {
+    var canSetImmediate = typeof window !== 'undefined'
+    && window.setImmediate;
+    var canPost = typeof window !== 'undefined'
+    && window.postMessage && window.addEventListener
+    ;
+
+    if (canSetImmediate) {
+        return function (f) { return window.setImmediate(f) };
+    }
+
+    if (canPost) {
+        var queue = [];
+        window.addEventListener('message', function (ev) {
+            if (ev.source === window && ev.data === 'process-tick') {
+                ev.stopPropagation();
+                if (queue.length > 0) {
+                    var fn = queue.shift();
+                    fn();
+                }
+            }
+        }, true);
+
+        return function nextTick(fn) {
+            queue.push(fn);
+            window.postMessage('process-tick', '*');
+        };
+    }
+
+    return function nextTick(fn) {
+        setTimeout(fn, 0);
+    };
+})();
+
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+
+process.binding = function (name) {
+    throw new Error('process.binding is not supported');
+}
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+    throw new Error('process.chdir is not supported');
+};
+
+},{}],2:[function(require,module,exports){
+(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
+
+var EventEmitter = exports.EventEmitter = process.EventEmitter;
+var isArray = typeof Array.isArray === 'function'
+    ? Array.isArray
+    : function (xs) {
+        return Object.prototype.toString.call(xs) === '[object Array]'
+    }
+;
+function indexOf (xs, x) {
+    if (xs.indexOf) return xs.indexOf(x);
+    for (var i = 0; i < xs.length; i++) {
+        if (x === xs[i]) return i;
+    }
+    return -1;
+}
+
+// By default EventEmitters will print a warning if more than
+// 10 listeners are added to it. This is a useful default which
+// helps finding memory leaks.
+//
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+var defaultMaxListeners = 10;
+EventEmitter.prototype.setMaxListeners = function(n) {
+  if (!this._events) this._events = {};
+  this._events.maxListeners = n;
+};
+
+
+EventEmitter.prototype.emit = function(type) {
+  // If there is no 'error' event listener then throw.
+  if (type === 'error') {
+    if (!this._events || !this._events.error ||
+        (isArray(this._events.error) && !this._events.error.length))
+    {
+      if (arguments[1] instanceof Error) {
+        throw arguments[1]; // Unhandled 'error' event
+      } else {
+        throw new Error("Uncaught, unspecified 'error' event.");
+      }
+      return false;
+    }
+  }
+
+  if (!this._events) return false;
+  var handler = this._events[type];
+  if (!handler) return false;
+
+  if (typeof handler == 'function') {
+    switch (arguments.length) {
+      // fast cases
+      case 1:
+        handler.call(this);
+        break;
+      case 2:
+        handler.call(this, arguments[1]);
+        break;
+      case 3:
+        handler.call(this, arguments[1], arguments[2]);
+        break;
+      // slower
+      default:
+        var args = Array.prototype.slice.call(arguments, 1);
+        handler.apply(this, args);
+    }
+    return true;
+
+  } else if (isArray(handler)) {
+    var args = Array.prototype.slice.call(arguments, 1);
+
+    var listeners = handler.slice();
+    for (var i = 0, l = listeners.length; i < l; i++) {
+      listeners[i].apply(this, args);
+    }
+    return true;
+
+  } else {
+    return false;
+  }
+};
+
+// EventEmitter is defined in src/node_events.cc
+// EventEmitter.prototype.emit() is also defined there.
+EventEmitter.prototype.addListener = function(type, listener) {
+  if ('function' !== typeof listener) {
+    throw new Error('addListener only takes instances of Function');
+  }
+
+  if (!this._events) this._events = {};
+
+  // To avoid recursion in the case that type == "newListeners"! Before
+  // adding it to the listeners, first emit "newListeners".
+  this.emit('newListener', type, listener);
+
+  if (!this._events[type]) {
+    // Optimize the case of one listener. Don't need the extra array object.
+    this._events[type] = listener;
+  } else if (isArray(this._events[type])) {
+
+    // Check for listener leak
+    if (!this._events[type].warned) {
+      var m;
+      if (this._events.maxListeners !== undefined) {
+        m = this._events.maxListeners;
+      } else {
+        m = defaultMaxListeners;
+      }
+
+      if (m && m > 0 && this._events[type].length > m) {
+        this._events[type].warned = true;
+        console.error('(node) warning: possible EventEmitter memory ' +
+                      'leak detected. %d listeners added. ' +
+                      'Use emitter.setMaxListeners() to increase limit.',
+                      this._events[type].length);
+        console.trace();
+      }
+    }
+
+    // If we've already got an array, just append.
+    this._events[type].push(listener);
+  } else {
+    // Adding the second element, need to change to array.
+    this._events[type] = [this._events[type], listener];
+  }
+
+  return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+  var self = this;
+  self.on(type, function g() {
+    self.removeListener(type, g);
+    listener.apply(this, arguments);
+  });
+
+  return this;
+};
+
+EventEmitter.prototype.removeListener = function(type, listener) {
+  if ('function' !== typeof listener) {
+    throw new Error('removeListener only takes instances of Function');
+  }
+
+  // does not use listeners(), so no side effect of creating _events[type]
+  if (!this._events || !this._events[type]) return this;
+
+  var list = this._events[type];
+
+  if (isArray(list)) {
+    var i = indexOf(list, listener);
+    if (i < 0) return this;
+    list.splice(i, 1);
+    if (list.length == 0)
+      delete this._events[type];
+  } else if (this._events[type] === listener) {
+    delete this._events[type];
+  }
+
+  return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+  if (arguments.length === 0) {
+    this._events = {};
+    return this;
+  }
+
+  // does not use listeners(), so no side effect of creating _events[type]
+  if (type && this._events && this._events[type]) this._events[type] = null;
+  return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+  if (!this._events) this._events = {};
+  if (!this._events[type]) this._events[type] = [];
+  if (!isArray(this._events[type])) {
+    this._events[type] = [this._events[type]];
+  }
+  return this._events[type];
+};
+
+})(require("__browserify_process"))
+},{"__browserify_process":1}],3:[function(require,module,exports){
+(function(){// jshint -W001
+
+"use strict";
+
+// Identifiers provided by the ECMAScript standard.
+
+exports.reservedVars = {
+	arguments : false,
+	NaN       : false
+};
+
+exports.ecmaIdentifiers = {
+	Array              : false,
+	Boolean            : false,
+	Date               : false,
+	decodeURI          : false,
+	decodeURIComponent : false,
+	encodeURI          : false,
+	encodeURIComponent : false,
+	Error              : false,
+	"eval"             : false,
+	EvalError          : false,
+	Function           : false,
+	hasOwnProperty     : false,
+	isFinite           : false,
+	isNaN              : false,
+	JSON               : false,
+	Math               : false,
+	Map                : false,
+	Number             : false,
+	Object             : false,
+	parseInt           : false,
+	parseFloat         : false,
+	RangeError         : false,
+	ReferenceError     : false,
+	RegExp             : false,
+	Set                : false,
+	String             : false,
+	SyntaxError        : false,
+	TypeError          : false,
+	URIError           : false,
+	WeakMap            : false
+};
+
+// Global variables commonly provided by a web browser environment.
+
+exports.browser = {
+	ArrayBuffer          : false,
+	ArrayBufferView      : false,
+	Audio                : false,
+	Blob                 : false,
+	addEventListener     : false,
+	applicationCache     : false,
+	atob                 : false,
+	blur                 : false,
+	btoa                 : false,
+	clearInterval        : false,
+	clearTimeout         : false,
+	close                : false,
+	closed               : false,
+	DataView             : false,
+	DOMParser            : false,
+	defaultStatus        : false,
+	document             : false,
+	Element              : false,
+	ElementTimeControl   : false,
+	event                : false,
+	FileReader           : false,
+	Float32Array         : false,
+	Float64Array         : false,
+	FormData             : false,
+	focus                : false,
+	frames               : false,
+	getComputedStyle     : false,
+	HTMLElement          : false,
+	HTMLAnchorElement    : false,
+	HTMLBaseElement      : false,
+	HTMLBlockquoteElement: false,
+	HTMLBodyElement      : false,
+	HTMLBRElement        : false,
+	HTMLButtonElement    : false,
+	HTMLCanvasElement    : false,
+	HTMLDirectoryElement : false,
+	HTMLDivElement       : false,
+	HTMLDListElement     : false,
+	HTMLFieldSetElement  : false,
+	HTMLFontElement      : false,
+	HTMLFormElement      : false,
+	HTMLFrameElement     : false,
+	HTMLFrameSetElement  : false,
+	HTMLHeadElement      : false,
+	HTMLHeadingElement   : false,
+	HTMLHRElement        : false,
+	HTMLHtmlElement      : false,
+	HTMLIFrameElement    : false,
+	HTMLImageElement     : false,
+	HTMLInputElement     : false,
+	HTMLIsIndexElement   : false,
+	HTMLLabelElement     : false,
+	HTMLLayerElement     : false,
+	HTMLLegendElement    : false,
+	HTMLLIElement        : false,
+	HTMLLinkElement      : false,
+	HTMLMapElement       : false,
+	HTMLMenuElement      : false,
+	HTMLMetaElement      : false,
+	HTMLModElement       : false,
+	HTMLObjectElement    : false,
+	HTMLOListElement     : false,
+	HTMLOptGroupElement  : false,
+	HTMLOptionElement    : false,
+	HTMLParagraphElement : false,
+	HTMLParamElement     : false,
+	HTMLPreElement       : false,
+	HTMLQuoteElement     : false,
+	HTMLScriptElement    : false,
+	HTMLSelectElement    : false,
+	HTMLStyleElement     : false,
+	HTMLTableCaptionElement: false,
+	HTMLTableCellElement : false,
+	HTMLTableColElement  : false,
+	HTMLTableElement     : false,
+	HTMLTableRowElement  : false,
+	HTMLTableSectionElement: false,
+	HTMLTextAreaElement  : false,
+	HTMLTitleElement     : false,
+	HTMLUListElement     : false,
+	HTMLVideoElement     : false,
+	history              : false,
+	Int16Array           : false,
+	Int32Array           : false,
+	Int8Array            : false,
+	Image                : false,
+	length               : false,
+	localStorage         : false,
+	location             : false,
+	MessageChannel       : false,
+	MessageEvent         : false,
+	MessagePort          : false,
+	moveBy               : false,
+	moveTo               : false,
+	MutationObserver     : false,
+	name                 : false,
+	Node                 : false,
+	NodeFilter           : false,
+	navigator            : false,
+	onbeforeunload       : true,
+	onblur               : true,
+	onerror              : true,
+	onfocus              : true,
+	onload               : true,
+	onresize             : true,
+	onunload             : true,
+	open                 : false,
+	openDatabase         : false,
+	opener               : false,
+	Option               : false,
+	parent               : false,
+	print                : false,
+	removeEventListener  : false,
+	resizeBy             : false,
+	resizeTo             : false,
+	screen               : false,
+	scroll               : false,
+	scrollBy             : false,
+	scrollTo             : false,
+	sessionStorage       : false,
+	setInterval          : false,
+	setTimeout           : false,
+	SharedWorker         : false,
+	status               : false,
+	SVGAElement          : false,
+	SVGAltGlyphDefElement: false,
+	SVGAltGlyphElement   : false,
+	SVGAltGlyphItemElement: false,
+	SVGAngle             : false,
+	SVGAnimateColorElement: false,
+	SVGAnimateElement    : false,
+	SVGAnimateMotionElement: false,
+	SVGAnimateTransformElement: false,
+	SVGAnimatedAngle     : false,
+	SVGAnimatedBoolean   : false,
+	SVGAnimatedEnumeration: false,
+	SVGAnimatedInteger   : false,
+	SVGAnimatedLength    : false,
+	SVGAnimatedLengthList: false,
+	SVGAnimatedNumber    : false,
+	SVGAnimatedNumberList: false,
+	SVGAnimatedPathData  : false,
+	SVGAnimatedPoints    : false,
+	SVGAnimatedPreserveAspectRatio: false,
+	SVGAnimatedRect      : false,
+	SVGAnimatedString    : false,
+	SVGAnimatedTransformList: false,
+	SVGAnimationElement  : false,
+	SVGCSSRule           : false,
+	SVGCircleElement     : false,
+	SVGClipPathElement   : false,
+	SVGColor             : false,
+	SVGColorProfileElement: false,
+	SVGColorProfileRule  : false,
+	SVGComponentTransferFunctionElement: false,
+	SVGCursorElement     : false,
+	SVGDefsElement       : false,
+	SVGDescElement       : false,
+	SVGDocument          : false,
+	SVGElement           : false,
+	SVGElementInstance   : false,
+	SVGElementInstanceList: false,
+	SVGEllipseElement    : false,
+	SVGExternalResourcesRequired: false,
+	SVGFEBlendElement    : false,
+	SVGFEColorMatrixElement: false,
+	SVGFEComponentTransferElement: false,
+	SVGFECompositeElement: false,
+	SVGFEConvolveMatrixElement: false,
+	SVGFEDiffuseLightingElement: false,
+	SVGFEDisplacementMapElement: false,
+	SVGFEDistantLightElement: false,
+	SVGFEFloodElement    : false,
+	SVGFEFuncAElement    : false,
+	SVGFEFuncBElement    : false,
+	SVGFEFuncGElement    : false,
+	SVGFEFuncRElement    : false,
+	SVGFEGaussianBlurElement: false,
+	SVGFEImageElement    : false,
+	SVGFEMergeElement    : false,
+	SVGFEMergeNodeElement: false,
+	SVGFEMorphologyElement: false,
+	SVGFEOffsetElement   : false,
+	SVGFEPointLightElement: false,
+	SVGFESpecularLightingElement: false,
+	SVGFESpotLightElement: false,
+	SVGFETileElement     : false,
+	SVGFETurbulenceElement: false,
+	SVGFilterElement     : false,
+	SVGFilterPrimitiveStandardAttributes: false,
+	SVGFitToViewBox      : false,
+	SVGFontElement       : false,
+	SVGFontFaceElement   : false,
+	SVGFontFaceFormatElement: false,
+	SVGFontFaceNameElement: false,
+	SVGFontFaceSrcElement: false,
+	SVGFontFaceUriElement: false,
+	SVGForeignObjectElement: false,
+	SVGGElement          : false,
+	SVGGlyphElement      : false,
+	SVGGlyphRefElement   : false,
+	SVGGradientElement   : false,
+	SVGHKernElement      : false,
+	SVGICCColor          : false,
+	SVGImageElement      : false,
+	SVGLangSpace         : false,
+	SVGLength            : false,
+	SVGLengthList        : false,
+	SVGLineElement       : false,
+	SVGLinearGradientElement: false,
+	SVGLocatable         : false,
+	SVGMPathElement      : false,
+	SVGMarkerElement     : false,
+	SVGMaskElement       : false,
+	SVGMatrix            : false,
+	SVGMetadataElement   : false,
+	SVGMissingGlyphElement: false,
+	SVGNumber            : false,
+	SVGNumberList        : false,
+	SVGPaint             : false,
+	SVGPathElement       : false,
+	SVGPathSeg           : false,
+	SVGPathSegArcAbs     : false,
+	SVGPathSegArcRel     : false,
+	SVGPathSegClosePath  : false,
+	SVGPathSegCurvetoCubicAbs: false,
+	SVGPathSegCurvetoCubicRel: false,
+	SVGPathSegCurvetoCubicSmoothAbs: false,
+	SVGPathSegCurvetoCubicSmoothRel: false,
+	SVGPathSegCurvetoQuadraticAbs: false,
+	SVGPathSegCurvetoQuadraticRel: false,
+	SVGPathSegCurvetoQuadraticSmoothAbs: false,
+	SVGPathSegCurvetoQuadraticSmoothRel: false,
+	SVGPathSegLinetoAbs  : false,
+	SVGPathSegLinetoHorizontalAbs: false,
+	SVGPathSegLinetoHorizontalRel: false,
+	SVGPathSegLinetoRel  : false,
+	SVGPathSegLinetoVerticalAbs: false,
+	SVGPathSegLinetoVerticalRel: false,
+	SVGPathSegList       : false,
+	SVGPathSegMovetoAbs  : false,
+	SVGPathSegMovetoRel  : false,
+	SVGPatternElement    : false,
+	SVGPoint             : false,
+	SVGPointList         : false,
+	SVGPolygonElement    : false,
+	SVGPolylineElement   : false,
+	SVGPreserveAspectRatio: false,
+	SVGRadialGradientElement: false,
+	SVGRect              : false,
+	SVGRectElement       : false,
+	SVGRenderingIntent   : false,
+	SVGSVGElement        : false,
+	SVGScriptElement     : false,
+	SVGSetElement        : false,
+	SVGStopElement       : false,
+	SVGStringList        : false,
+	SVGStylable          : false,
+	SVGStyleElement      : false,
+	SVGSwitchElement     : false,
+	SVGSymbolElement     : false,
+	SVGTRefElement       : false,
+	SVGTSpanElement      : false,
+	SVGTests             : false,
+	SVGTextContentElement: false,
+	SVGTextElement       : false,
+	SVGTextPathElement   : false,
+	SVGTextPositioningElement: false,
+	SVGTitleElement      : false,
+	SVGTransform         : false,
+	SVGTransformList     : false,
+	SVGTransformable     : false,
+	SVGURIReference      : false,
+	SVGUnitTypes         : false,
+	SVGUseElement        : false,
+	SVGVKernElement      : false,
+	SVGViewElement       : false,
+	SVGViewSpec          : false,
+	SVGZoomAndPan        : false,
+	TimeEvent            : false,
+	top                  : false,
+	Uint16Array          : false,
+	Uint32Array          : false,
+	Uint8Array           : false,
+	Uint8ClampedArray    : false,
+	WebSocket            : false,
+	window               : false,
+	Worker               : false,
+	XMLHttpRequest       : false,
+	XMLSerializer        : false,
+	XPathEvaluator       : false,
+	XPathException       : false,
+	XPathExpression      : false,
+	XPathNamespace       : false,
+	XPathNSResolver      : false,
+	XPathResult          : false
+};
+
+exports.devel = {
+	alert  : false,
+	confirm: false,
+	console: false,
+	Debug  : false,
+	opera  : false,
+	prompt : false
+};
+
+exports.worker = {
+	importScripts: true,
+	postMessage  : true,
+	self         : true
+};
+
+// Widely adopted global names that are not part of ECMAScript standard
+exports.nonstandard = {
+	escape  : false,
+	unescape: false
+};
+
+// Globals provided by popular JavaScript environments.
+
+exports.couch = {
+	"require" : false,
+	respond   : false,
+	getRow    : false,
+	emit      : false,
+	send      : false,
+	start     : false,
+	sum       : false,
+	log       : false,
+	exports   : false,
+	module    : false,
+	provides  : false
+};
+
+exports.node = {
+	__filename    : false,
+	__dirname     : false,
+	Buffer        : false,
+	DataView      : false,
+	console       : false,
+	exports       : true,  // In Node it is ok to exports = module.exports = foo();
+	GLOBAL        : false,
+	global        : false,
+	module        : false,
+	process       : false,
+	require       : false,
+	setTimeout    : false,
+	clearTimeout  : false,
+	setInterval   : false,
+	clearInterval : false,
+	setImmediate  : false, // v0.9.1+
+	clearImmediate: false  // v0.9.1+
+};
+
+exports.phantom = {
+	phantom      : true,
+	require      : true,
+	WebPage      : true
+};
+
+exports.rhino = {
+	defineClass  : false,
+	deserialize  : false,
+	gc           : false,
+	help         : false,
+	importPackage: false,
+	"java"       : false,
+	load         : false,
+	loadClass    : false,
+	print        : false,
+	quit         : false,
+	readFile     : false,
+	readUrl      : false,
+	runCommand   : false,
+	seal         : false,
+	serialize    : false,
+	spawn        : false,
+	sync         : false,
+	toint32      : false,
+	version      : false
+};
+
+exports.wsh = {
+	ActiveXObject            : true,
+	Enumerator               : true,
+	GetObject                : true,
+	ScriptEngine             : true,
+	ScriptEngineBuildVersion : true,
+	ScriptEngineMajorVersion : true,
+	ScriptEngineMinorVersion : true,
+	VBArray                  : true,
+	WSH                      : true,
+	WScript                  : true,
+	XDomainRequest           : true
+};
+
+// Globals provided by popular JavaScript libraries.
+
+exports.dojo = {
+	dojo     : false,
+	dijit    : false,
+	dojox    : false,
+	define	 : false,
+	"require": false
+};
+
+exports.jquery = {
+	"$"    : false,
+	jQuery : false
+};
+
+exports.mootools = {
+	"$"           : false,
+	"$$"          : false,
+	Asset         : false,
+	Browser       : false,
+	Chain         : false,
+	Class         : false,
+	Color         : false,
+	Cookie        : false,
+	Core          : false,
+	Document      : false,
+	DomReady      : false,
+	DOMEvent      : false,
+	DOMReady      : false,
+	Drag          : false,
+	Element       : false,
+	Elements      : false,
+	Event         : false,
+	Events        : false,
+	Fx            : false,
+	Group         : false,
+	Hash          : false,
+	HtmlTable     : false,
+	Iframe        : false,
+	IframeShim    : false,
+	InputValidator: false,
+	instanceOf    : false,
+	Keyboard      : false,
+	Locale        : false,
+	Mask          : false,
+	MooTools      : false,
+	Native        : false,
+	Options       : false,
+	OverText      : false,
+	Request       : false,
+	Scroller      : false,
+	Slick         : false,
+	Slider        : false,
+	Sortables     : false,
+	Spinner       : false,
+	Swiff         : false,
+	Tips          : false,
+	Type          : false,
+	typeOf        : false,
+	URI           : false,
+	Window        : false
+};
+
+exports.prototypejs = {
+	"$"               : false,
+	"$$"              : false,
+	"$A"              : false,
+	"$F"              : false,
+	"$H"              : false,
+	"$R"              : false,
+	"$break"          : false,
+	"$continue"       : false,
+	"$w"              : false,
+	Abstract          : false,
+	Ajax              : false,
+	Class             : false,
+	Enumerable        : false,
+	Element           : false,
+	Event             : false,
+	Field             : false,
+	Form              : false,
+	Hash              : false,
+	Insertion         : false,
+	ObjectRange       : false,
+	PeriodicalExecuter: false,
+	Position          : false,
+	Prototype         : false,
+	Selector          : false,
+	Template          : false,
+	Toggle            : false,
+	Try               : false,
+	Autocompleter     : false,
+	Builder           : false,
+	Control           : false,
+	Draggable         : false,
+	Draggables        : false,
+	Droppables        : false,
+	Effect            : false,
+	Sortable          : false,
+	SortableObserver  : false,
+	Sound             : false,
+	Scriptaculous     : false
+};
+
+exports.yui = {
+	YUI       : false,
+	Y         : false,
+	YUI_config: false
+};
+
+
+})()
+},{}],4:[function(require,module,exports){
+"use strict";
+
+var state = {
+	syntax: {},
+
+	reset: function () {
+		this.tokens = {
+			prev: null,
+			next: null,
+			curr: null
+		};
+
+		this.option = {};
+		this.ignored = {};
+		this.directive = {};
+		this.jsonMode = false;
+		this.jsonWarnings = [];
+		this.lines = [];
+		this.tab = "";
+		this.cache = {}; // Node.JS doesn't have Map. Sniff.
+	}
+};
+
+exports.state = state;
+
+},{}],5:[function(require,module,exports){
+(function(){"use strict";
+
+exports.register = function (linter) {
+	// Check for properties named __proto__. This special property was
+	// deprecated and then re-introduced for ES6.
+
+	linter.on("Identifier", function style_scanProto(data) {
+		if (linter.getOption("proto")) {
+			return;
+		}
+
+		if (data.name === "__proto__") {
+			linter.warn("W103", {
+				line: data.line,
+				char: data.char,
+				data: [ data.name ]
+			});
+		}
+	});
+
+	// Check for properties named __iterator__. This is a special property
+	// available only in browsers with JavaScript 1.7 implementation.
+
+	linter.on("Identifier", function style_scanIterator(data) {
+		if (linter.getOption("iterator")) {
+			return;
+		}
+
+		if (data.name === "__iterator__") {
+			linter.warn("W104", {
+				line: data.line,
+				char: data.char,
+				data: [ data.name ]
+			});
+		}
+	});
+
+	// Check for dangling underscores.
+
+	linter.on("Identifier", function style_scanDangling(data) {
+		if (!linter.getOption("nomen")) {
+			return;
+		}
+
+		// Underscore.js
+		if (data.name === "_") {
+			return;
+		}
+
+		// In Node, __dirname and __filename should be ignored.
+		if (linter.getOption("node")) {
+			if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
+				return;
+			}
+		}
+
+		if (/^(_+.*|.*_+)$/.test(data.name)) {
+			linter.warn("W105", {
+				line: data.line,
+				char: data.from,
+				data: [ "dangling '_'", data.name ]
+			});
+		}
+	});
+
+	// Check that all identifiers are using camelCase notation.
+	// Exceptions: names like MY_VAR and _myVar.
+
+	linter.on("Identifier", function style_scanCamelCase(data) {
+		if (!linter.getOption("camelcase")) {
+			return;
+		}
+
+		if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
+			linter.warn("W106", {
+				line: data.line,
+				char: data.from,
+				data: [ data.name ]
+			});
+		}
+	});
+
+	// Enforce consistency in style of quoting.
+
+	linter.on("String", function style_scanQuotes(data) {
+		var quotmark = linter.getOption("quotmark");
+		var code;
+
+		if (!quotmark) {
+			return;
+		}
+
+		// If quotmark is set to 'single' warn about all double-quotes.
+
+		if (quotmark === "single" && data.quote !== "'") {
+			code = "W109";
+		}
+
+		// If quotmark is set to 'double' warn about all single-quotes.
+
+		if (quotmark === "double" && data.quote !== "\"") {
+			code = "W108";
+		}
+
+		// If quotmark is set to true, remember the first quotation style
+		// and then warn about all others.
+
+		if (quotmark === true) {
+			if (!linter.getCache("quotmark")) {
+				linter.setCache("quotmark", data.quote);
+			}
+
+			if (linter.getCache("quotmark") !== data.quote) {
+				code = "W110";
+			}
+		}
+
+		if (code) {
+			linter.warn(code, {
+				line: data.line,
+				char: data.char,
+			});
+		}
+	});
+
+	linter.on("Number", function style_scanNumbers(data) {
+		if (data.value.charAt(0) === ".") {
+			// Warn about a leading decimal point.
+			linter.warn("W008", {
+				line: data.line,
+				char: data.char,
+				data: [ data.value ]
+			});
+		}
+
+		if (data.value.substr(data.value.length - 1) === ".") {
+			// Warn about a trailing decimal point.
+			linter.warn("W047", {
+				line: data.line,
+				char: data.char,
+				data: [ data.value ]
+			});
+		}
+
+		if (/^00+/.test(data.value)) {
+			// Multiple leading zeroes.
+			linter.warn("W046", {
+				line: data.line,
+				char: data.char,
+				data: [ data.value ]
+			});
+		}
+	});
+
+	// Warn about script URLs.
+
+	linter.on("String", function style_scanJavaScriptURLs(data) {
+		var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
+
+		if (linter.getOption("scripturl")) {
+			return;
+		}
+
+		if (re.test(data.value)) {
+			linter.warn("W107", {
+				line: data.line,
+				char: data.char
+			});
+		}
+	});
+};
+})()
+},{}],6:[function(require,module,exports){
+/*
+ * Regular expressions. Some of these are stupidly long.
+ */
+
+/*jshint maxlen:1000 */
+
+"use string";
+
+// Unsafe comment or string (ax)
+exports.unsafeString =
+	/@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
+
+// Unsafe characters that are silently deleted by one or more browsers (cx)
+exports.unsafeChars =
+	/[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+// Characters in strings that need escaping (nx and nxg)
+exports.needEsc =
+	/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+exports.needEscGlobal =
+	/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+
+// Star slash (lx)
+exports.starSlash = /\*\//;
+
+// Identifier (ix)
+exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
+
+// JavaScript URL (jx)
+exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
+
+// Catches /* falls through */ comments (ft)
+//exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
+exports.fallsThrough = /^\s*\/\/\s*Falls?\sthrough.*\s*$/;
+
+},{}],7:[function(require,module,exports){
+(function(global){/*global window, global*/
+var util = require("util")
+var assert = require("assert")
+
+var slice = Array.prototype.slice
+var console
+var times = {}
+
+if (typeof global !== "undefined" && global.console) {
+    console = global.console
+} else if (typeof window !== "undefined" && window.console) {
+    console = window.console
+} else {
+    console = window.console = {}
+}
+
+var functions = [
+    [log, "log"]
+    , [info, "info"]
+    , [warn, "warn"]
+    , [error, "error"]
+    , [time, "time"]
+    , [timeEnd, "timeEnd"]
+    , [trace, "trace"]
+    , [dir, "dir"]
+    , [assert, "assert"]
+]
+
+for (var i = 0; i < functions.length; i++) {
+    var tuple = functions[i]
+    var f = tuple[0]
+    var name = tuple[1]
+
+    if (!console[name]) {
+        console[name] = f
+    }
+}
+
+module.exports = console
+
+function log() {}
+
+function info() {
+    console.log.apply(console, arguments)
+}
+
+function warn() {
+    console.log.apply(console, arguments)
+}
+
+function error() {
+    console.warn.apply(console, arguments)
+}
+
+function time(label) {
+    times[label] = Date.now()
+}
+
+function timeEnd(label) {
+    var time = times[label]
+    if (!time) {
+        throw new Error("No such label: " + label)
+    }
+
+    var duration = Date.now() - time
+    console.log(label + ": " + duration + "ms")
+}
+
+function trace() {
+    var err = new Error()
+    err.name = "Trace"
+    err.message = util.format.apply(null, arguments)
+    console.error(err.stack)
+}
+
+function dir(object) {
+    console.log(util.inspect(object) + "\n")
+}
+
+function assert(expression) {
+    if (!expression) {
+        var arr = slice.call(arguments, 1)
+        assert.ok(false, util.format.apply(null, arr))
+    }
+}
+
+})(window)
+},{"util":8,"assert":9}],10:[function(require,module,exports){
+(function(){/*
+ * Lexical analysis and token construction.
+ */
+
+"use strict";
+
+var _      = require("underscore");
+var events = require("events");
+var reg    = require("./reg.js");
+var state  = require("./state.js").state;
+
+// Some of these token types are from JavaScript Parser API
+// while others are specific to JSHint parser.
+// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
+
+var Token = {
+	Identifier: 1,
+	Punctuator: 2,
+	NumericLiteral: 3,
+	StringLiteral: 4,
+	Comment: 5,
+	Keyword: 6,
+	NullLiteral: 7,
+	BooleanLiteral: 8,
+	RegExp: 9
+};
+
+// This is auto generated from the unicode tables.
+// The tables are at:
+// http://www.fileformat.info/info/unicode/category/Lu/list.htm
+// http://www.fileformat.info/info/unicode/category/Ll/list.htm
+// http://www.fileformat.info/info/unicode/category/Lt/list.htm
+// http://www.fileformat.info/info/unicode/category/Lm/list.htm
+// http://www.fileformat.info/info/unicode/category/Lo/list.htm
+// http://www.fileformat.info/info/unicode/category/Nl/list.htm
+
+var unicodeLetterTable = [
+	170, 170, 181, 181, 186, 186, 192, 214,
+	216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
+	880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
+	910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
+	1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
+	1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
+	1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
+	1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
+	2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
+	2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
+	2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
+	2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
+	2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
+	2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
+	2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
+	2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
+	2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
+	2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
+	2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
+	2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
+	3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
+	3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
+	3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
+	3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
+	3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
+	3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
+	3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
+	3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
+	3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
+	3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
+	3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
+	4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
+	4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
+	4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
+	4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
+	4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
+	4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
+	5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
+	5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
+	6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
+	6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
+	6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
+	6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
+	7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
+	7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
+	8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
+	8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
+	8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
+	8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
+	8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
+	8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
+	8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
+	11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
+	11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
+	11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
+	11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
+	12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
+	12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
+	12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
+	19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
+	42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
+	42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
+	42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
+	43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
+	43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
+	43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
+	43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
+	43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
+	43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
+	43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
+	43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
+	55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
+	64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
+	64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
+	64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
+	64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
+	65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
+	65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
+	65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
+	65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
+	65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
+	66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
+	66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
+	67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
+	67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
+	68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
+	68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
+	69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
+	92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
+	119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
+	119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
+	120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
+	120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
+	120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
+	120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
+	120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
+	131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
+	177984, 177984, 178205, 178205, 194560, 195101
+];
+
+var identifierStartTable = [];
+
+for (var i = 0; i < 128; i++) {
+	identifierStartTable[i] =
+		i === 36 ||           // $
+		i >= 65 && i <= 90 || // A-Z
+		i === 95 ||           // _
+		i >= 97 && i <= 122;  // a-z
+}
+
+var identifierPartTable = [];
+
+for (var i = 0; i < 128; i++) {
+	identifierPartTable[i] =
+		identifierStartTable[i] || // $, _, A-Z, a-z
+		i >= 48 && i <= 57;        // 0-9
+}
+
+// Object that handles postponed lexing verifications that checks the parsed
+// environment state.
+
+function asyncTrigger() {
+	var _checks = [];
+
+	return {
+		push: function (fn) {
+			_checks.push(fn);
+		},
+
+		check: function () {
+			for (var check in _checks) {
+				_checks[check]();
+			}
+
+			_checks.splice(0, _checks.length);
+		}
+	};
+}
+
+/*
+ * Lexer for JSHint.
+ *
+ * This object does a char-by-char scan of the provided source code
+ * and produces a sequence of tokens.
+ *
+ *   var lex = new Lexer("var i = 0;");
+ *   lex.start();
+ *   lex.token(); // returns the next token
+ *
+ * You have to use the token() method to move the lexer forward
+ * but you don't have to use its return value to get tokens. In addition
+ * to token() method returning the next token, the Lexer object also
+ * emits events.
+ *
+ *   lex.on("Identifier", function (data) {
+ *     if (data.name.indexOf("_") >= 0) {
+ *       // Produce a warning.
+ *     }
+ *   });
+ *
+ * Note that the token() method returns tokens in a JSLint-compatible
+ * format while the event emitter uses a slightly modified version of
+ * Mozilla's JavaScript Parser API. Eventually, we will move away from
+ * JSLint format.
+ */
+function Lexer(source) {
+	var lines = source;
+
+	if (typeof lines === "string") {
+		lines = lines
+			.replace(/\r\n/g, "\n")
+			.replace(/\r/g, "\n")
+			.split("\n");
+	}
+
+	// If the first line is a shebang (#!), make it a blank and move on.
+	// Shebangs are used by Node scripts.
+
+	if (lines[0] && lines[0].substr(0, 2) === "#!") {
+		lines[0] = "";
+	}
+
+	this.emitter = new events.EventEmitter();
+	this.source = source;
+	this.lines = lines;
+	this.prereg = true;
+
+	this.line = 0;
+	this.char = 1;
+	this.from = 1;
+	this.input = "";
+
+	for (var i = 0; i < state.option.indent; i += 1) {
+		state.tab += " ";
+	}
+}
+
+Lexer.prototype = {
+	_lines: [],
+
+	get lines() {
+		this._lines = state.lines;
+		return this._lines;
+	},
+
+	set lines(val) {
+		this._lines = val;
+		state.lines = this._lines;
+	},
+
+	/*
+	 * Return the next i character without actually moving the
+	 * char pointer.
+	 */
+	peek: function (i) {
+		return this.input.charAt(i || 0);
+	},
+
+	/*
+	 * Move the char pointer forward i times.
+	 */
+	skip: function (i) {
+		i = i || 1;
+		this.char += i;
+		this.input = this.input.slice(i);
+	},
+
+	/*
+	 * Subscribe to a token event. The API for this method is similar
+	 * Underscore.js i.e. you can subscribe to multiple events with
+	 * one call:
+	 *
+	 *   lex.on("Identifier Number", function (data) {
+	 *     // ...
+	 *   });
+	 */
+	on: function (names, listener) {
+		names.split(" ").forEach(function (name) {
+			this.emitter.on(name, listener);
+		}.bind(this));
+	},
+
+	/*
+	 * Trigger a token event. All arguments will be passed to each
+	 * listener.
+	 */
+	trigger: function () {
+		this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
+	},
+
+	/*
+	 * Postpone a token event. the checking condition is set as
+	 * last parameter, and the trigger function is called in a
+	 * stored callback. To be later called using the check() function
+	 * by the parser. This avoids parser's peek() to give the lexer
+	 * a false context.
+	 */
+	triggerAsync: function (type, args, checks, fn) {
+		checks.push(function () {
+			if (fn()) {
+				this.trigger(type, args);
+			}
+		}.bind(this));
+	},
+
+	/*
+	 * Extract a punctuator out of the next sequence of characters
+	 * or return 'null' if its not possible.
+	 *
+	 * This method's implementation was heavily influenced by the
+	 * scanPunctuator function in the Esprima parser's source code.
+	 */
+	scanPunctuator: function () {
+		var ch1 = this.peek();
+		var ch2, ch3, ch4;
+
+		switch (ch1) {
+		// Most common single-character punctuators
+		case ".":
+			if ((/^[0-9]$/).test(this.peek(1))) {
+				return null;
+			}
+			if (this.peek(1) === "." && this.peek(2) === ".") {
+				return {
+					type: Token.Punctuator,
+					value: "..."
+				};
+			}
+			/* falls through */
+		case "(":
+		case ")":
+		case ";":
+		case ",":
+		case "{":
+		case "}":
+		case "[":
+		case "]":
+		case ":":
+		case "~":
+		case "?":
+			return {
+				type: Token.Punctuator,
+				value: ch1
+			};
+
+		// A pound sign (for Node shebangs)
+		case "#":
+			return {
+				type: Token.Punctuator,
+				value: ch1
+			};
+
+		// We're at the end of input
+		case "":
+			return null;
+		}
+
+		// Peek more characters
+
+		ch2 = this.peek(1);
+		ch3 = this.peek(2);
+		ch4 = this.peek(3);
+
+		// 4-character punctuator: >>>=
+
+		if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
+			return {
+				type: Token.Punctuator,
+				value: ">>>="
+			};
+		}
+
+		// 3-character punctuators: === !== >>> <<= >>=
+
+		if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
+			return {
+				type: Token.Punctuator,
+				value: "==="
+			};
+		}
+
+		if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
+			return {
+				type: Token.Punctuator,
+				value: "!=="
+			};
+		}
+
+		if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
+			return {
+				type: Token.Punctuator,
+				value: ">>>"
+			};
+		}
+
+		if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
+			return {
+				type: Token.Punctuator,
+				value: "<<="
+			};
+		}
+
+		if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
+			return {
+				type: Token.Punctuator,
+				value: ">>="
+			};
+		}
+
+		// Fat arrow punctuator
+		if (ch1 === "=" && ch2 === ">") {
+			return {
+				type: Token.Punctuator,
+				value: ch1 + ch2
+			};
+		}
+
+		// 2-character punctuators: <= >= == != ++ -- << >> && ||
+		// += -= *= %= &= |= ^= (but not /=, see below)
+		if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
+			return {
+				type: Token.Punctuator,
+				value: ch1 + ch2
+			};
+		}
+
+		if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
+			if (ch2 === "=") {
+				return {
+					type: Token.Punctuator,
+					value: ch1 + ch2
+				};
+			}
+
+			return {
+				type: Token.Punctuator,
+				value: ch1
+			};
+		}
+
+		// Special case: /=. We need to make sure that this is an
+		// operator and not a regular expression.
+
+		if (ch1 === "/") {
+			if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
+				// /= is not a part of a regular expression, return it as a
+				// punctuator.
+				return {
+					type: Token.Punctuator,
+					value: "/="
+				};
+			}
+
+			return {
+				type: Token.Punctuator,
+				value: "/"
+			};
+		}
+
+		return null;
+	},
+
+	/*
+	 * Extract a comment out of the next sequence of characters and/or
+	 * lines or return 'null' if its not possible. Since comments can
+	 * span across multiple lines this method has to move the char
+	 * pointer.
+	 *
+	 * In addition to normal JavaScript comments (// and /*) this method
+	 * also recognizes JSHint- and JSLint-specific comments such as
+	 * /*jshint, /*jslint, /*globals and so on.
+	 */
+	scanComments: function () {
+		var ch1 = this.peek();
+		var ch2 = this.peek(1);
+		var rest = this.input.substr(2);
+		var startLine = this.line;
+		var startChar = this.char;
+
+		// Create a comment token object and make sure it
+		// has all the data JSHint needs to work with special
+		// comments.
+
+		function commentToken(label, body, opt) {
+			var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
+			var isSpecial = false;
+			var value = label + body;
+			var commentType = "plain";
+			opt = opt || {};
+
+			if (opt.isMultiline) {
+				value += "*/";
+			}
+
+			special.forEach(function (str) {
+				if (isSpecial) {
+					return;
+				}
+
+				// Don't recognize any special comments other than jshint for single-line
+				// comments. This introduced many problems with legit comments.
+				if (label === "//" && str !== "jshint") {
+					return;
+				}
+
+				if (body.substr(0, str.length) === str) {
+					isSpecial = true;
+					label = label + str;
+					body = body.substr(str.length);
+				}
+
+				if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
+					isSpecial = true;
+					label = label + " " + str;
+					body = body.substr(str.length + 1);
+				}
+
+				if (!isSpecial) {
+					return;
+				}
+
+				switch (str) {
+				case "member":
+					commentType = "members";
+					break;
+				case "global":
+					commentType = "globals";
+					break;
+				default:
+					commentType = str;
+				}
+			});
+
+			return {
+				type: Token.Comment,
+				commentType: commentType,
+				value: value,
+				body: body,
+				isSpecial: isSpecial,
+				isMultiline: opt.isMultiline || false,
+				isMalformed: opt.isMalformed || false
+			};
+		}
+
+		// End of unbegun comment. Raise an error and skip that input.
+		if (ch1 === "*" && ch2 === "/") {
+			this.trigger("error", {
+				code: "E018",
+				line: startLine,
+				character: startChar
+			});
+
+			this.skip(2);
+			return null;
+		}
+
+		// Comments must start either with // or /*
+		if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
+			return null;
+		}
+
+		// One-line comment
+		if (ch2 === "/") {
+			this.skip(this.input.length); // Skip to the EOL.
+			return commentToken("//", rest);
+		}
+
+		var body = "";
+
+		/* Multi-line comment */
+		if (ch2 === "*") {
+			this.skip(2);
+
+			while (this.peek() !== "*" || this.peek(1) !== "/") {
+				if (this.peek() === "") { // End of Line
+					body += "\n";
+
+					// If we hit EOF and our comment is still unclosed,
+					// trigger an error and end the comment implicitly.
+					if (!this.nextLine()) {
+						this.trigger("error", {
+							code: "E017",
+							line: startLine,
+							character: startChar
+						});
+
+						return commentToken("/*", body, {
+							isMultiline: true,
+							isMalformed: true
+						});
+					}
+				} else {
+					body += this.peek();
+					this.skip();
+				}
+			}
+
+			this.skip(2);
+			return commentToken("/*", body, { isMultiline: true });
+		}
+	},
+
+	/*
+	 * Extract a keyword out of the next sequence of characters or
+	 * return 'null' if its not possible.
+	 */
+	scanKeyword: function () {
+		var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
+		var keywords = [
+			"if", "in", "do", "var", "for", "new",
+			"try", "let", "this", "else", "case",
+			"void", "with", "enum", "while", "break",
+			"catch", "throw", "const", "yield", "class",
+			"super", "return", "typeof", "delete",
+			"switch", "export", "import", "default",
+			"finally", "extends", "function", "continue",
+			"debugger", "instanceof"
+		];
+
+		if (result && keywords.indexOf(result[0]) >= 0) {
+			return {
+				type: Token.Keyword,
+				value: result[0]
+			};
+		}
+
+		return null;
+	},
+
+	/*
+	 * Extract a JavaScript identifier out of the next sequence of
+	 * characters or return 'null' if its not possible. In addition,
+	 * to Identifier this method can also produce BooleanLiteral
+	 * (true/false) and NullLiteral (null).
+	 */
+	scanIdentifier: function () {
+		var id = "";
+		var index = 0;
+		var type, char;
+
+		// Detects any character in the Unicode categories "Uppercase
+		// letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
+		// (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
+		// "Letter number (Nl)".
+		//
+		// Both approach and unicodeLetterTable were borrowed from
+		// Google's Traceur.
+
+		function isUnicodeLetter(code) {
+			for (var i = 0; i < unicodeLetterTable.length;) {
+				if (code < unicodeLetterTable[i++]) {
+					return false;
+				}
+
+				if (code <= unicodeLetterTable[i++]) {
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		function isHexDigit(str) {
+			return (/^[0-9a-fA-F]$/).test(str);
+		}
+
+		var readUnicodeEscapeSequence = function () {
+			/*jshint validthis:true */
+			index += 1;
+
+			if (this.peek(index) !== "u") {
+				return null;
+			}
+
+			var ch1 = this.peek(index + 1);
+			var ch2 = this.peek(index + 2);
+			var ch3 = this.peek(index + 3);
+			var ch4 = this.peek(index + 4);
+			var code;
+
+			if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
+				code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
+
+				if (isUnicodeLetter(code)) {
+					index += 5;
+					return "\\u" + ch1 + ch2 + ch3 + ch4;
+				}
+
+				return null;
+			}
+
+			return null;
+		}.bind(this);
+
+		var getIdentifierStart = function () {
+			/*jshint validthis:true */
+			var chr = this.peek(index);
+			var code = chr.charCodeAt(0);
+
+			if (code === 92) {
+				return readUnicodeEscapeSequence();
+			}
+
+			if (code < 128) {
+				if (identifierStartTable[code]) {
+					index += 1;
+					return chr;
+				}
+
+				return null;
+			}
+
+			if (isUnicodeLetter(code)) {
+				index += 1;
+				return chr;
+			}
+
+			return null;
+		}.bind(this);
+
+		var getIdentifierPart = function () {
+			/*jshint validthis:true */
+			var chr = this.peek(index);
+			var code = chr.charCodeAt(0);
+
+			if (code === 92) {
+				return readUnicodeEscapeSequence();
+			}
+
+			if (code < 128) {
+				if (identifierPartTable[code]) {
+					index += 1;
+					return chr;
+				}
+
+				return null;
+			}
+
+			if (isUnicodeLetter(code)) {
+				index += 1;
+				return chr;
+			}
+
+			return null;
+		}.bind(this);
+
+		char = getIdentifierStart();
+		if (char === null) {
+			return null;
+		}
+
+		id = char;
+		for (;;) {
+			char = getIdentifierPart();
+
+			if (char === null) {
+				break;
+			}
+
+			id += char;
+		}
+
+		switch (id) {
+		case "true":
+		case "false":
+			type = Token.BooleanLiteral;
+			break;
+		case "null":
+			type = Token.NullLiteral;
+			break;
+		default:
+			type = Token.Identifier;
+		}
+
+		return {
+			type: type,
+			value: id
+		};
+	},
+
+	/*
+	 * Extract a numeric literal out of the next sequence of
+	 * characters or return 'null' if its not possible. This method
+	 * supports all numeric literals described in section 7.8.3
+	 * of the EcmaScript 5 specification.
+	 *
+	 * This method's implementation was heavily influenced by the
+	 * scanNumericLiteral function in the Esprima parser's source code.
+	 */
+	scanNumericLiteral: function () {
+		var index = 0;
+		var value = "";
+		var length = this.input.length;
+		var char = this.peek(index);
+		var bad;
+
+		function isDecimalDigit(str) {
+			return (/^[0-9]$/).test(str);
+		}
+
+		function isOctalDigit(str) {
+			return (/^[0-7]$/).test(str);
+		}
+
+		function isHexDigit(str) {
+			return (/^[0-9a-fA-F]$/).test(str);
+		}
+
+		function isIdentifierStart(ch) {
+			return (ch === "$") || (ch === "_") || (ch === "\\") ||
+				(ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
+		}
+
+		// Numbers must start either with a decimal digit or a point.
+
+		if (char !== "." && !isDecimalDigit(char)) {
+			return null;
+		}
+
+		if (char !== ".") {
+			value = this.peek(index);
+			index += 1;
+			char = this.peek(index);
+
+			if (value === "0") {
+				// Base-16 numbers.
+				if (char === "x" || char === "X") {
+					index += 1;
+					value += char;
+
+					while (index < length) {
+						char = this.peek(index);
+						if (!isHexDigit(char)) {
+							break;
+						}
+						value += char;
+						index += 1;
+					}
+
+					if (value.length <= 2) { // 0x
+						return {
+							type: Token.NumericLiteral,
+							value: value,
+							isMalformed: true
+						};
+					}
+
+					if (index < length) {
+						char = this.peek(index);
+						if (isIdentifierStart(char)) {
+							return null;
+						}
+					}
+
+					return {
+						type: Token.NumericLiteral,
+						value: value,
+						base: 16,
+						isMalformed: false
+					};
+				}
+
+				// Base-8 numbers.
+				if (isOctalDigit(char)) {
+					index += 1;
+					value += char;
+					bad = false;
+
+					while (index < length) {
+						char = this.peek(index);
+
+						// Numbers like '019' (note the 9) are not valid octals
+						// but we still parse them and mark as malformed.
+
+						if (isDecimalDigit(char)) {
+							bad = true;
+						} else if (!isOctalDigit(char)) {
+							break;
+						}
+						value += char;
+						index += 1;
+					}
+
+					if (index < length) {
+						char = this.peek(index);
+						if (isIdentifierStart(char)) {
+							return null;
+						}
+					}
+
+					return {
+						type: Token.NumericLiteral,
+						value: value,
+						base: 8,
+						isMalformed: false
+					};
+				}
+
+				// Decimal numbers that start with '0' such as '09' are illegal
+				// but we still parse them and return as malformed.
+
+				if (isDecimalDigit(char)) {
+					index += 1;
+					value += char;
+				}
+			}
+
+			while (index < length) {
+				char = this.peek(index);
+				if (!isDecimalDigit(char)) {
+					break;
+				}
+				value += char;
+				index += 1;
+			}
+		}
+
+		// Decimal digits.
+
+		if (char === ".") {
+			value += char;
+			index += 1;
+
+			while (index < length) {
+				char = this.peek(index);
+				if (!isDecimalDigit(char)) {
+					break;
+				}
+				value += char;
+				index += 1;
+			}
+		}
+
+		// Exponent part.
+
+		if (char === "e" || char === "E") {
+			value += char;
+			index += 1;
+			char = this.peek(index);
+
+			if (char === "+" || char === "-") {
+				value += this.peek(index);
+				index += 1;
+			}
+
+			char = this.peek(index);
+			if (isDecimalDigit(char)) {
+				value += char;
+				index += 1;
+
+				while (index < length) {
+					char = this.peek(index);
+					if (!isDecimalDigit(char)) {
+						break;
+					}
+					value += char;
+					index += 1;
+				}
+			} else {
+				return null;
+			}
+		}
+
+		if (index < length) {
+			char = this.peek(index);
+			if (isIdentifierStart(char)) {
+				return null;
+			}
+		}
+
+		return {
+			type: Token.NumericLiteral,
+			value: value,
+			base: 10,
+			isMalformed: !isFinite(value)
+		};
+	},
+
+	/*
+	 * Extract a string out of the next sequence of characters and/or
+	 * lines or return 'null' if its not possible. Since strings can
+	 * span across multiple lines this method has to move the char
+	 * pointer.
+	 *
+	 * This method recognizes pseudo-multiline JavaScript strings:
+	 *
+	 *   var str = "hello\
+	 *   world";
+	 */
+	scanStringLiteral: function (checks) {
+		/*jshint loopfunc:true */
+		var quote = this.peek();
+
+		// String must start with a quote.
+		if (quote !== "\"" && quote !== "'") {
+			return null;
+		}
+
+		// In JSON strings must always use double quotes.
+		this.triggerAsync("warning", {
+			code: "W108",
+			line: this.line,
+			character: this.char // +1?
+		}, checks, function () { return state.jsonMode && quote !== "\""; });
+
+		var value = "";
+		var startLine = this.line;
+		var startChar = this.char;
+		var allowNewLine = false;
+
+		this.skip();
+
+		while (this.peek() !== quote) {
+			while (this.peek() === "") { // End Of Line
+
+				// If an EOL is not preceded by a backslash, show a warning
+				// and proceed like it was a legit multi-line string where
+				// author simply forgot to escape the newline symbol.
+				//
+				// Another approach is to implicitly close a string on EOL
+				// but it generates too many false positives.
+
+				if (!allowNewLine) {
+					this.trigger("warning", {
+						code: "W112",
+						line: this.line,
+						character: this.char
+					});
+				} else {
+					allowNewLine = false;
+
+					// Otherwise show a warning if multistr option was not set.
+					// For JSON, show warning no matter what.
+
+					this.triggerAsync("warning", {
+						code: "W043",
+						line: this.line,
+						character: this.char
+					}, checks, function () { return !state.option.multistr; });
+
+					this.triggerAsync("warning", {
+						code: "W042",
+						line: this.line,
+						character: this.char
+					}, checks, function () { return state.jsonMode && state.option.multistr; });
+				}
+
+				// If we get an EOF inside of an unclosed string, show an
+				// error and implicitly close it at the EOF point.
+
+				if (!this.nextLine()) {
+					this.trigger("error", {
+						code: "E029",
+						line: startLine,
+						character: startChar
+					});
+
+					return {
+						type: Token.StringLiteral,
+						value: value,
+						isUnclosed: true,
+						quote: quote
+					};
+				}
+			}
+
+			allowNewLine = false;
+			var char = this.peek();
+			var jump = 1; // A length of a jump, after we're done
+			              // parsing this character.
+
+			if (char < " ") {
+				// Warn about a control character in a string.
+				this.trigger("warning", {
+					code: "W113",
+					line: this.line,
+					character: this.char,
+					data: [ "<non-printable>" ]
+				});
+			}
+
+			// Special treatment for some escaped characters.
+
+			if (char === "\\") {
+				this.skip();
+				char = this.peek();
+
+				switch (char) {
+				case "'":
+					this.triggerAsync("warning", {
+						code: "W114",
+						line: this.line,
+						character: this.char,
+						data: [ "\\'" ]
+					}, checks, function () {return state.jsonMode; });
+					break;
+				case "b":
+					char = "\b";
+					break;
+				case "f":
+					char = "\f";
+					break;
+				case "n":
+					char = "\n";
+					break;
+				case "r":
+					char = "\r";
+					break;
+				case "t":
+					char = "\t";
+					break;
+				case "0":
+					char = "\0";
+
+					// Octal literals fail in strict mode.
+					// Check if the number is between 00 and 07.
+					var n = parseInt(this.peek(1), 10);
+					this.triggerAsync("warning", {
+						code: "W115",
+						line: this.line,
+						character: this.char
+					}, checks,
+					function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
+					break;
+				case "u":
+					char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
+					jump = 5;
+					break;
+				case "v":
+					this.triggerAsync("warning", {
+						code: "W114",
+						line: this.line,
+						character: this.char,
+						data: [ "\\v" ]
+					}, checks, function () { return state.jsonMode; });
+
+					char = "\v";
+					break;
+				case "x":
+					var	x = parseInt(this.input.substr(1, 2), 16);
+
+					this.triggerAsync("warning", {
+						code: "W114",
+						line: this.line,
+						character: this.char,
+						data: [ "\\x-" ]
+					}, checks, function () { return state.jsonMode; });
+
+					char = String.fromCharCode(x);
+					jump = 3;
+					break;
+				case "\\":
+				case "\"":
+				case "/":
+					break;
+				case "":
+					allowNewLine = true;
+					char = "";
+					break;
+				case "!":
+					if (value.slice(value.length - 2) === "<") {
+						break;
+					}
+
+					/*falls through */
+				default:
+					// Weird escaping.
+					this.trigger("warning", {
+						code: "W044",
+						line: this.line,
+						character: this.char
+					});
+				}
+			}
+
+			value += char;
+			this.skip(jump);
+		}
+
+		this.skip();
+		return {
+			type: Token.StringLiteral,
+			value: value,
+			isUnclosed: false,
+			quote: quote
+		};
+	},
+
+	/*
+	 * Extract a regular expression out of the next sequence of
+	 * characters and/or lines or return 'null' if its not possible.
+	 *
+	 * This method is platform dependent: it accepts almost any
+	 * regular expression values but then tries to compile and run
+	 * them using system's RegExp object. This means that there are
+	 * rare edge cases where one JavaScript engine complains about
+	 * your regular expression while others don't.
+	 */
+	scanRegExp: function () {
+		var index = 0;
+		var length = this.input.length;
+		var char = this.peek();
+		var value = char;
+		var body = "";
+		var flags = [];
+		var malformed = false;
+		var isCharSet = false;
+		var terminated;
+
+		var scanUnexpectedChars = function () {
+			// Unexpected control character
+			if (char < " ") {
+				malformed = true;
+				this.trigger("warning", {
+					code: "W048",
+					line: this.line,
+					character: this.char
+				});
+			}
+
+			// Unexpected escaped character
+			if (char === "<") {
+				malformed = true;
+				this.trigger("warning", {
+					code: "W049",
+					line: this.line,
+					character: this.char,
+					data: [ char ]
+				});
+			}
+		}.bind(this);
+
+		// Regular expressions must start with '/'
+		if (!this.prereg || char !== "/") {
+			return null;
+		}
+
+		index += 1;
+		terminated = false;
+
+		// Try to get everything in between slashes. A couple of
+		// cases aside (see scanUnexpectedChars) we don't really
+		// care whether the resulting expression is valid or not.
+		// We will check that later using the RegExp object.
+
+		while (index < length) {
+			char = this.peek(index);
+			value += char;
+			body += char;
+
+			if (isCharSet) {
+				if (char === "]") {
+					if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
+						isCharSet = false;
+					}
+				}
+
+				if (char === "\\") {
+					index += 1;
+					char = this.peek(index);
+					body += char;
+					value += char;
+
+					scanUnexpectedChars();
+				}
+
+				index += 1;
+				continue;
+			}
+
+			if (char === "\\") {
+				index += 1;
+				char = this.peek(index);
+				body += char;
+				value += char;
+
+				scanUnexpectedChars();
+
+				if (char === "/") {
+					index += 1;
+					continue;
+				}
+
+				if (char === "[") {
+					index += 1;
+					continue;
+				}
+			}
+
+			if (char === "[") {
+				isCharSet = true;
+				index += 1;
+				continue;
+			}
+
+			if (char === "/") {
+				body = body.substr(0, body.length - 1);
+				terminated = true;
+				index += 1;
+				break;
+			}
+
+			index += 1;
+		}
+
+		// A regular expression that was never closed is an
+		// error from which we cannot recover.
+
+		if (!terminated) {
+			this.trigger("error", {
+				code: "E015",
+				line: this.line,
+				character: this.from
+			});
+
+			return void this.trigger("fatal", {
+				line: this.line,
+				from: this.from
+			});
+		}
+
+		// Parse flags (if any).
+
+		while (index < length) {
+			char = this.peek(index);
+			if (!/[gim]/.test(char)) {
+				break;
+			}
+			flags.push(char);
+			value += char;
+			index += 1;
+		}
+
+		// Check regular expression for correctness.
+
+		try {
+			new RegExp(body, flags.join(""));
+		} catch (err) {
+			malformed = true;
+			this.trigger("error", {
+				code: "E016",
+				line: this.line,
+				character: this.char,
+				data: [ err.message ] // Platform dependent!
+			});
+		}
+
+		return {
+			type: Token.RegExp,
+			value: value,
+			flags: flags,
+			isMalformed: malformed
+		};
+	},
+
+	/*
+	 * Scan for any occurence of mixed tabs and spaces. If smarttabs option
+	 * is on, ignore tabs followed by spaces.
+	 *
+	 * Tabs followed by one space followed by a block comment are allowed.
+	 */
+	scanMixedSpacesAndTabs: function () {
+		var at, match;
+
+		if (state.option.smarttabs) {
+			// Negative look-behind for "//"
+			match = this.input.match(/(\/\/|^\s?\*)? \t/);
+			at = match && !match[1] ? 0 : -1;
+		} else {
+			at = this.input.search(/ \t|\t [^\*]/);
+		}
+
+		return at;
+	},
+
+	/*
+	 * Scan for characters that get silently deleted by one or more browsers.
+	 */
+	scanUnsafeChars: function () {
+		return this.input.search(reg.unsafeChars);
+	},
+
+	/*
+	 * Produce the next raw token or return 'null' if no tokens can be matched.
+	 * This method skips over all space characters.
+	 */
+	next: function (checks) {
+		this.from = this.char;
+
+		// Move to the next non-space character.
+		var start;
+		if (/\s/.test(this.peek())) {
+			start = this.char;
+
+			while (/\s/.test(this.peek())) {
+				this.from += 1;
+				this.skip();
+			}
+
+			if (this.peek() === "") { // EOL
+				if (!/^\s*$/.test(this.lines[this.line - 1]) && state.option.trailing) {
+					this.trigger("warning", { code: "W102", line: this.line, character: start });
+				}
+			}
+		}
+
+		// Methods that work with multi-line structures and move the
+		// character pointer.
+
+		var match = this.scanComments() ||
+			this.scanStringLiteral(checks);
+
+		if (match) {
+			return match;
+		}
+
+		// Methods that don't move the character pointer.
+
+		match =
+			this.scanRegExp() ||
+			this.scanPunctuator() ||
+			this.scanKeyword() ||
+			this.scanIdentifier() ||
+			this.scanNumericLiteral();
+
+		if (match) {
+			this.skip(match.value.length);
+			return match;
+		}
+
+		// No token could be matched, give up.
+
+		return null;
+	},
+
+	/*
+	 * Switch to the next line and reset all char pointers. Once
+	 * switched, this method also checks for mixed spaces and tabs
+	 * and other minor warnings.
+	 */
+	nextLine: function () {
+		var char;
+
+		if (this.line >= this.lines.length) {
+			return false;
+		}
+
+		this.input = this.lines[this.line];
+		this.line += 1;
+		this.char = 1;
+		this.from = 1;
+
+		char = this.scanMixedSpacesAndTabs();
+		if (char >= 0) {
+			this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
+		}
+
+		this.input = this.input.replace(/\t/g, state.tab);
+		char = this.scanUnsafeChars();
+
+		if (char >= 0) {
+			this.trigger("warning", { code: "W100", line: this.line, character: char });
+		}
+
+		// If there is a limit on line length, warn when lines get too
+		// long.
+
+		if (state.option.maxlen && state.option.maxlen < this.input.length) {
+			this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
+		}
+
+		return true;
+	},
+
+	/*
+	 * This is simply a synonym for nextLine() method with a friendlier
+	 * public name.
+	 */
+	start: function () {
+		this.nextLine();
+	},
+
+	/*
+	 * Produce the next token. This function is called by advance() to get
+	 * the next token. It retuns a token in a JSLint-compatible format.
+	 */
+	token: function () {
+		/*jshint loopfunc:true */
+		var checks = asyncTrigger();
+		var token;
+
+
+		function isReserved(token, isProperty) {
+			if (!token.reserved) {
+				return false;
+			}
+
+			if (token.meta && token.meta.isFutureReservedWord) {
+				// ES3 FutureReservedWord in an ES5 environment.
+				if (state.option.inES5(true) && !token.meta.es5) {
+					return false;
+				}
+
+				// Some ES5 FutureReservedWord identifiers are active only
+				// within a strict mode environment.
+				if (token.meta.strictOnly) {
+					if (!state.option.strict && !state.directive["use strict"]) {
+						return false;
+					}
+				}
+
+				if (isProperty) {
+					return false;
+				}
+			}
+
+			return true;
+		}
+
+		// Produce a token object.
+		var create = function (type, value, isProperty) {
+			/*jshint validthis:true */
+			var obj;
+
+			if (type !== "(endline)" && type !== "(end)") {
+				this.prereg = false;
+			}
+
+			if (type === "(punctuator)") {
+				switch (value) {
+				case ".":
+				case ")":
+				case "~":
+				case "#":
+				case "]":
+					this.prereg = false;
+					break;
+				default:
+					this.prereg = true;
+				}
+
+				obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+			}
+
+			if (type === "(identifier)") {
+				if (value === "return" || value === "case" || value === "typeof") {
+					this.prereg = true;
+				}
+
+				if (_.has(state.syntax, value)) {
+					obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+
+					// If this can't be a reserved keyword, reset the object.
+					if (!isReserved(obj, isProperty && type === "(identifier)")) {
+						obj = null;
+					}
+				}
+			}
+
+			if (!obj) {
+				obj = Object.create(state.syntax[type]);
+			}
+
+			obj.identifier = (type === "(identifier)");
+			obj.type = obj.type || type;
+			obj.value = value;
+			obj.line = this.line;
+			obj.character = this.char;
+			obj.from = this.from;
+
+			if (isProperty && obj.identifier) {
+				obj.isProperty = isProperty;
+			}
+
+			obj.check = checks.check;
+
+			return obj;
+		}.bind(this);
+
+		for (;;) {
+			if (!this.input.length) {
+				return create(this.nextLine() ? "(endline)" : "(end)", "");
+			}
+
+			token = this.next(checks);
+
+			if (!token) {
+				if (this.input.length) {
+					// Unexpected character.
+					this.trigger("error", {
+						code: "E024",
+						line: this.line,
+						character: this.char,
+						data: [ this.peek() ]
+					});
+
+					this.input = "";
+				}
+
+				continue;
+			}
+
+			switch (token.type) {
+			case Token.StringLiteral:
+				this.triggerAsync("String", {
+					line: this.line,
+					char: this.char,
+					from: this.from,
+					value: token.value,
+					quote: token.quote
+				}, checks, function () { return true; });
+
+				return create("(string)", token.value);
+			case Token.Identifier:
+				this.trigger("Identifier", {
+					line: this.line,
+					char: this.char,
+					from: this.form,
+					name: token.value,
+					isProperty: state.tokens.curr.id === "."
+				});
+
+				/* falls through */
+			case Token.Keyword:
+			case Token.NullLiteral:
+			case Token.BooleanLiteral:
+				return create("(identifier)", token.value, state.tokens.curr.id === ".");
+
+			case Token.NumericLiteral:
+				if (token.isMalformed) {
+					this.trigger("warning", {
+						code: "W045",
+						line: this.line,
+						character: this.char,
+						data: [ token.value ]
+					});
+				}
+
+				this.triggerAsync("warning", {
+					code: "W114",
+					line: this.line,
+					character: this.char,
+					data: [ "0x-" ]
+				}, checks, function () { return token.base === 16 && state.jsonMode; });
+
+				this.triggerAsync("warning", {
+					code: "W115",
+					line: this.line,
+					character: this.char
+				}, checks, function () {
+					return state.directive["use strict"] && token.base === 8;
+				});
+
+				this.trigger("Number", {
+					line: this.line,
+					char: this.char,
+					from: this.from,
+					value: token.value,
+					base: token.base,
+					isMalformed: token.malformed
+				});
+
+				return create("(number)", token.value);
+
+			case Token.RegExp:
+				return create("(regexp)", token.value);
+
+			case Token.Comment:
+				state.tokens.curr.comment = true;
+
+				if (token.isSpecial) {
+					return {
+						value: token.value,
+						body: token.body,
+						type: token.commentType,
+						isSpecial: token.isSpecial,
+						line: this.line,
+						character: this.char,
+						from: this.from
+					};
+				}
+
+				break;
+
+			case "":
+				break;
+
+			default:
+				return create("(punctuator)", token.value);
+			}
+		}
+	}
+};
+
+exports.Lexer = Lexer;
+
+})()
+},{"events":2,"./reg.js":6,"./state.js":4,"underscore":11}],"jshint":[function(require,module,exports){
+module.exports=require('E/GbHF');
+},{}],"E/GbHF":[function(require,module,exports){
+(function(){/*!
+ * JSHint, by JSHint Community.
+ *
+ * This file (and this file only) is licensed under the same slightly modified
+ * MIT license that JSLint is. It stops evil-doers everywhere:
+ *
+ *	 Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
+ *
+ *	 Permission is hereby granted, free of charge, to any person obtaining
+ *	 a copy of this software and associated documentation files (the "Software"),
+ *	 to deal in the Software without restriction, including without limitation
+ *	 the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *	 and/or sell copies of the Software, and to permit persons to whom
+ *	 the Software is furnished to do so, subject to the following conditions:
+ *
+ *	 The above copyright notice and this permission notice shall be included
+ *	 in all copies or substantial portions of the Software.
+ *
+ *	 The Software shall be used for Good, not Evil.
+ *
+ *	 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *	 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *	 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *	 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *	 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *	 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *	 DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*jshint quotmark:double */
+/*global console:true */
+/*exported console */
+
+var _        = require("underscore");
+var events   = require("events");
+var vars     = require("../shared/vars.js");
+var messages = require("../shared/messages.js");
+var Lexer    = require("./lex.js").Lexer;
+var reg      = require("./reg.js");
+var state    = require("./state.js").state;
+var style    = require("./style.js");
+
+// We need this module here because environments such as IE and Rhino
+// don't necessarilly expose the 'console' API and browserify uses
+// it to log things. It's a sad state of affair, really.
+var console = require("console-browserify");
+
+// We build the application inside a function so that we produce only a singleton
+// variable. That function will be invoked immediately, and its return value is
+// the JSHINT function itself.
+
+var JSHINT = (function () {
+	"use strict";
+
+	var anonname, // The guessed name for anonymous functions.
+		api, // Extension API
+
+		// These are operators that should not be used with the ! operator.
+		bang = {
+			"<"  : true,
+			"<=" : true,
+			"==" : true,
+			"===": true,
+			"!==": true,
+			"!=" : true,
+			">"  : true,
+			">=" : true,
+			"+"  : true,
+			"-"  : true,
+			"*"  : true,
+			"/"  : true,
+			"%"  : true
+		},
+
+		// These are the JSHint boolean options.
+		boolOptions = {
+			asi         : true, // if automatic semicolon insertion should be tolerated
+			bitwise     : true, // if bitwise operators should not be allowed
+			boss        : true, // if advanced usage of assignments should be allowed
+			browser     : true, // if the standard browser globals should be predefined
+			camelcase   : true, // if identifiers should be required in camel case
+			couch       : true, // if CouchDB globals should be predefined
+			curly       : true, // if curly braces around all blocks should be required
+			debug       : true, // if debugger statements should be allowed
+			devel       : true, // if logging globals should be predefined (console, alert, etc.)
+			dojo        : true, // if Dojo Toolkit globals should be predefined
+			eqeqeq      : true, // if === should be required
+			eqnull      : true, // if == null comparisons should be tolerated
+			es3         : true, // if ES3 syntax should be allowed
+			es5         : true, // if ES5 syntax should be allowed (is now set per default)
+			esnext      : true, // if es.next specific syntax should be allowed
+			moz         : true, // if mozilla specific syntax should be allowed
+			evil        : true, // if eval should be allowed
+			expr        : true, // if ExpressionStatement should be allowed as Programs
+			forin       : true, // if for in statements must filter
+			funcscope   : true, // if only function scope should be used for scope tests
+			gcl         : true, // if JSHint should be compatible with Google Closure Linter
+			globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
+			immed       : true, // if immediate invocations must be wrapped in parens
+			iterator    : true, // if the `__iterator__` property should be allowed
+			jquery      : true, // if jQuery globals should be predefined
+			lastsemic   : true, // if semicolons may be ommitted for the trailing
+			                    // statements inside of a one-line blocks.
+			laxbreak    : true, // if line breaks should not be checked
+			laxcomma    : true, // if line breaks should not be checked around commas
+			loopfunc    : true, // if functions should be allowed to be defined within
+			                    // loops
+			mootools    : true, // if MooTools globals should be predefined
+			multistr    : true, // allow multiline strings
+			newcap      : true, // if constructor names must be capitalized
+			noarg       : true, // if arguments.caller and arguments.callee should be
+			                    // disallowed
+			node        : true, // if the Node.js environment globals should be
+			                    // predefined
+			noempty     : true, // if empty blocks should be disallowed
+			nonew       : true, // if using `new` for side-effects should be disallowed
+			nonstandard : true, // if non-standard (but widely adopted) globals should
+			                    // be predefined
+			nomen       : true, // if names should be checked
+			onevar      : true, // if only one var statement per function should be
+			                    // allowed
+			passfail    : true, // if the scan should stop on first error
+			phantom     : true, // if PhantomJS symbols should be allowed
+			plusplus    : true, // if increment/decrement should not be allowed
+			proto       : true, // if the `__proto__` property should be allowed
+			prototypejs : true, // if Prototype and Scriptaculous globals should be
+			                    // predefined
+			rhino       : true, // if the Rhino environment globals should be predefined
+			undef       : true, // if variables should be declared before used
+			scripturl   : true, // if script-targeted URLs should be tolerated
+			shadow      : true, // if variable shadowing should be tolerated
+			smarttabs   : true, // if smarttabs should be tolerated
+			                    // (http://www.emacswiki.org/emacs/SmartTabs)
+			strict      : true, // require the "use strict"; pragma
+			sub         : true, // if all forms of subscript notation are tolerated
+			supernew    : true, // if `new function () { ... };` and `new Object;`
+			                    // should be tolerated
+			trailing    : true, // if trailing whitespace rules apply
+			validthis   : true, // if 'this' inside a non-constructor function is valid.
+			                    // This is a function scoped option only.
+			withstmt    : true, // if with statements should be allowed
+			white       : true, // if strict whitespace rules apply
+			worker      : true, // if Web Worker script symbols should be allowed
+			wsh         : true, // if the Windows Scripting Host environment globals
+			                    // should be predefined
+			yui         : true, // YUI variables should be predefined
+
+			// Obsolete options
+			onecase     : true, // if one case switch statements should be allowed
+			regexp      : true, // if the . should not be allowed in regexp literals
+			regexdash   : true  // if unescaped first/last dash (-) inside brackets
+			                    // should be tolerated
+		},
+
+		// These are the JSHint options that can take any value
+		// (we use this object to detect invalid options)
+		valOptions = {
+			maxlen       : false,
+			indent       : false,
+			maxerr       : false,
+			predef       : false,
+			quotmark     : false, //'single'|'double'|true
+			scope        : false,
+			maxstatements: false, // {int} max statements per function
+			maxdepth     : false, // {int} max nested block depth per function
+			maxparams    : false, // {int} max params per function
+			maxcomplexity: false, // {int} max cyclomatic complexity per function
+			unused       : true,  // warn if variables are unused. Available options:
+			                      //   false    - don't check for unused variables
+			                      //   true     - "vars" + check last function param
+			                      //   "vars"   - skip checking unused function params
+			                      //   "strict" - "vars" + check all function params
+			latedef      : false  // warn if the variable is used before its definition
+			                      //   false    - don't emit any warnings
+			                      //   true     - warn if any variable is used before its definition
+			                      //   "nofunc" - warn for any variable but function declarations
+		},
+
+		// These are JSHint boolean options which are shared with JSLint
+		// where the definition in JSHint is opposite JSLint
+		invertedOptions = {
+			bitwise : true,
+			forin   : true,
+			newcap  : true,
+			nomen   : true,
+			plusplus: true,
+			regexp  : true,
+			undef   : true,
+			white   : true,
+
+			// Inverted and renamed, use JSHint name here
+			eqeqeq  : true,
+			onevar  : true,
+			strict  : true
+		},
+
+		// These are JSHint boolean options which are shared with JSLint
+		// where the name has been changed but the effect is unchanged
+		renamedOptions = {
+			eqeq   : "eqeqeq",
+			vars   : "onevar",
+			windows: "wsh",
+			sloppy : "strict"
+		},
+
+		declared, // Globals that were declared using /*global ... */ syntax.
+		exported, // Variables that are used outside of the current file.
+
+		functionicity = [
+			"closure", "exception", "global", "label",
+			"outer", "unused", "var"
+		],
+
+		funct, // The current function
+		functions, // All of the functions
+
+		global, // The global scope
+		implied, // Implied globals
+		inblock,
+		indent,
+		lookahead,
+		lex,
+		member,
+		membersOnly,
+		noreach,
+		predefined,		// Global variables defined by option
+
+		scope,  // The current scope
+		stack,
+		unuseds,
+		urls,
+		warnings,
+
+		extraModules = [],
+		emitter = new events.EventEmitter();
+
+	function checkOption(name, t) {
+		name = name.trim();
+
+		if (/^[+-]W\d{3}$/g.test(name)) {
+			return true;
+		}
+
+		if (valOptions[name] === undefined && boolOptions[name] === undefined) {
+			if (t.type !== "jslint") {
+				error("E001", t, name);
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	function isString(obj) {
+		return Object.prototype.toString.call(obj) === "[object String]";
+	}
+
+	function isIdentifier(tkn, value) {
+		if (!tkn)
+			return false;
+
+		if (!tkn.identifier || tkn.value !== value)
+			return false;
+
+		return true;
+	}
+
+	function isReserved(token) {
+		if (!token.reserved) {
+			return false;
+		}
+
+		if (token.meta && token.meta.isFutureReservedWord) {
+			// ES3 FutureReservedWord in an ES5 environment.
+			if (state.option.inES5(true) && !token.meta.es5) {
+				return false;
+			}
+
+			// Some ES5 FutureReservedWord identifiers are active only
+			// within a strict mode environment.
+			if (token.meta.strictOnly) {
+				if (!state.option.strict && !state.directive["use strict"]) {
+					return false;
+				}
+			}
+
+			if (token.isProperty) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	function supplant(str, data) {
+		return str.replace(/\{([^{}]*)\}/g, function (a, b) {
+			var r = data[b];
+			return typeof r === "string" || typeof r === "number" ? r : a;
+		});
+	}
+
+	function combine(t, o) {
+		var n;
+		for (n in o) {
+			if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
+				t[n] = o[n];
+			}
+		}
+	}
+
+	function updatePredefined() {
+		Object.keys(JSHINT.blacklist).forEach(function (key) {
+			delete predefined[key];
+		});
+	}
+
+	function assume() {
+		if (state.option.es5) {
+			warning("I003");
+		}
+		if (state.option.couch) {
+			combine(predefined, vars.couch);
+		}
+
+		if (state.option.rhino) {
+			combine(predefined, vars.rhino);
+		}
+
+		if (state.option.phantom) {
+			combine(predefined, vars.phantom);
+		}
+
+		if (state.option.prototypejs) {
+			combine(predefined, vars.prototypejs);
+		}
+
+		if (state.option.node) {
+			combine(predefined, vars.node);
+		}
+
+		if (state.option.devel) {
+			combine(predefined, vars.devel);
+		}
+
+		if (state.option.dojo) {
+			combine(predefined, vars.dojo);
+		}
+
+		if (state.option.browser) {
+			combine(predefined, vars.browser);
+		}
+
+		if (state.option.nonstandard) {
+			combine(predefined, vars.nonstandard);
+		}
+
+		if (state.option.jquery) {
+			combine(predefined, vars.jquery);
+		}
+
+		if (state.option.mootools) {
+			combine(predefined, vars.mootools);
+		}
+
+		if (state.option.worker) {
+			combine(predefined, vars.worker);
+		}
+
+		if (state.option.wsh) {
+			combine(predefined, vars.wsh);
+		}
+
+		if (state.option.globalstrict && state.option.strict !== false) {
+			state.option.strict = true;
+		}
+
+		if (state.option.yui) {
+			combine(predefined, vars.yui);
+		}
+
+		// Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
+
+		state.option.inMoz = function (strict) {
+			if (strict) {
+				return state.option.moz && !state.option.esnext;
+			}
+			return state.option.moz;
+		};
+
+		state.option.inESNext = function (strict) {
+			if (strict) {
+				return !state.option.moz && state.option.esnext;
+			}
+			return state.option.moz || state.option.esnext;
+		};
+
+		state.option.inES5 = function (/* strict */) {
+			return !state.option.es3;
+		};
+
+		state.option.inES3 = function (strict) {
+			if (strict) {
+				return !state.option.moz && !state.option.esnext && state.option.es3;
+			}
+			return state.option.es3;
+		};
+	}
+
+	// Produce an error warning.
+	function quit(code, line, chr) {
+		var percentage = Math.floor((line / state.lines.length) * 100);
+		var message = messages.errors[code].desc;
+
+		throw {
+			name: "JSHintError",
+			line: line,
+			character: chr,
+			message: message + " (" + percentage + "% scanned).",
+			raw: message
+		};
+	}
+
+	function isundef(scope, code, token, a) {
+		return JSHINT.undefs.push([scope, code, token, a]);
+	}
+
+	function warning(code, t, a, b, c, d) {
+		var ch, l, w, msg;
+
+		if (/^W\d{3}$/.test(code)) {
+			if (state.ignored[code])
+				return;
+
+			msg = messages.warnings[code];
+		} else if (/E\d{3}/.test(code)) {
+			msg = messages.errors[code];
+		} else if (/I\d{3}/.test(code)) {
+			msg = messages.info[code];
+		}
+
+		t = t || state.tokens.next;
+		if (t.id === "(end)") {  // `~
+			t = state.tokens.curr;
+		}
+
+		l = t.line || 0;
+		ch = t.from || 0;
+
+		w = {
+			id: "(error)",
+			raw: msg.desc,
+			code: msg.code,
+			evidence: state.lines[l - 1] || "",
+			line: l,
+			character: ch,
+			scope: JSHINT.scope,
+			a: a,
+			b: b,
+			c: c,
+			d: d
+		};
+
+		w.reason = supplant(msg.desc, w);
+		JSHINT.errors.push(w);
+
+		if (state.option.passfail) {
+			quit("E042", l, ch);
+		}
+
+		warnings += 1;
+		if (warnings >= state.option.maxerr) {
+			quit("E043", l, ch);
+		}
+
+		return w;
+	}
+
+	function warningAt(m, l, ch, a, b, c, d) {
+		return warning(m, {
+			line: l,
+			from: ch
+		}, a, b, c, d);
+	}
+
+	function error(m, t, a, b, c, d) {
+		warning(m, t, a, b, c, d);
+	}
+
+	function errorAt(m, l, ch, a, b, c, d) {
+		return error(m, {
+			line: l,
+			from: ch
+		}, a, b, c, d);
+	}
+
+	// Tracking of "internal" scripts, like eval containing a static string
+	function addInternalSrc(elem, src) {
+		var i;
+		i = {
+			id: "(internal)",
+			elem: elem,
+			value: src
+		};
+		JSHINT.internals.push(i);
+		return i;
+	}
+
+	function addlabel(t, type, tkn, islet) {
+		// Define t in the current function in the current scope.
+		if (type === "exception") {
+			if (_.has(funct["(context)"], t)) {
+				if (funct[t] !== true && !state.option.node) {
+					warning("W002", state.tokens.next, t);
+				}
+			}
+		}
+
+		if (_.has(funct, t) && !funct["(global)"]) {
+			if (funct[t] === true) {
+				if (state.option.latedef) {
+					if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
+							!_.contains([funct[t], type], "unction")) {
+						warning("W003", state.tokens.next, t);
+					}
+				}
+			} else {
+				if (!state.option.shadow && type !== "exception" ||
+							(funct["(blockscope)"].getlabel(t))) {
+					warning("W004", state.tokens.next, t);
+				}
+			}
+		}
+
+		// a double definition of a let variable in same block throws a TypeError
+		//if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
+		//	error("E044", state.tokens.next, t);
+		//}
+
+		// if the identifier is from a let, adds it only to the current blockscope
+		if (islet) {
+			funct["(blockscope)"].current.add(t, type, state.tokens.curr);
+		} else {
+
+			funct[t] = type;
+
+			if (tkn) {
+				funct["(tokens)"][t] = tkn;
+			}
+
+			if (funct["(global)"]) {
+				global[t] = funct;
+				if (_.has(implied, t)) {
+					if (state.option.latedef) {
+						if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
+								!_.contains([funct[t], type], "unction")) {
+							warning("W003", state.tokens.next, t);
+						}
+					}
+
+					delete implied[t];
+				}
+			} else {
+				scope[t] = funct;
+			}
+		}
+	}
+
+	function doOption() {
+		var nt = state.tokens.next;
+		var body = nt.body.split(",").map(function (s) { return s.trim(); });
+		var predef = {};
+
+		if (nt.type === "globals") {
+			body.forEach(function (g) {
+				g = g.split(":");
+				var key = g[0];
+				var val = g[1];
+
+				if (key.charAt(0) === "-") {
+					key = key.slice(1);
+					val = false;
+
+					JSHINT.blacklist[key] = key;
+					updatePredefined();
+				} else {
+					predef[key] = (val === "true");
+				}
+			});
+
+			combine(predefined, predef);
+
+			for (var key in predef) {
+				if (_.has(predef, key)) {
+					declared[key] = nt;
+				}
+			}
+		}
+
+		if (nt.type === "exported") {
+			body.forEach(function (e) {
+				exported[e] = true;
+			});
+		}
+
+		if (nt.type === "members") {
+			membersOnly = membersOnly || {};
+
+			body.forEach(function (m) {
+				var ch1 = m.charAt(0);
+				var ch2 = m.charAt(m.length - 1);
+
+				if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
+					m = m
+						.substr(1, m.length - 2)
+						.replace("\\b", "\b")
+						.replace("\\t", "\t")
+						.replace("\\n", "\n")
+						.replace("\\v", "\v")
+						.replace("\\f", "\f")
+						.replace("\\r", "\r")
+						.replace("\\\\", "\\")
+						.replace("\\\"", "\"");
+				}
+
+				membersOnly[m] = false;
+			});
+		}
+
+		var numvals = [
+			"maxstatements",
+			"maxparams",
+			"maxdepth",
+			"maxcomplexity",
+			"maxerr",
+			"maxlen",
+			"indent"
+		];
+
+		if (nt.type === "jshint" || nt.type === "jslint") {
+			body.forEach(function (g) {
+				g = g.split(":");
+				var key = (g[0] || "").trim();
+				var val = (g[1] || "").trim();
+
+				if (!checkOption(key, nt)) {
+					return;
+				}
+
+				if (numvals.indexOf(key) >= 0) {
+
+					// GH988 - numeric options can be disabled by setting them to `false`
+					if (val !== "false") {
+						val = +val;
+
+						if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
+							error("E032", nt, g[1].trim());
+							return;
+						}
+
+						if (key === "indent") {
+							state.option["(explicitIndent)"] = true;
+						}
+						state.option[key] = val;
+					} else {
+						if (key === "indent") {
+							state.option["(explicitIndent)"] = false;
+						} else {
+							state.option[key] = false;
+						}
+					}
+
+					return;
+				}
+
+				if (key === "validthis") {
+					// `validthis` is valid only within a function scope.
+					if (funct["(global)"]) {
+						error("E009");
+					} else {
+						if (val === "true" || val === "false") {
+							state.option.validthis = (val === "true");
+						} else {
+							error("E002", nt);
+						}
+					}
+					return;
+				}
+
+				if (key === "quotmark") {
+					switch (val) {
+					case "true":
+					case "false":
+						state.option.quotmark = (val === "true");
+						break;
+					case "double":
+					case "single":
+						state.option.quotmark = val;
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "unused") {
+					switch (val) {
+					case "true":
+						state.option.unused = true;
+						break;
+					case "false":
+						state.option.unused = false;
+						break;
+					case "vars":
+					case "strict":
+						state.option.unused = val;
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "latedef") {
+					switch (val) {
+					case "true":
+						state.option.latedef = true;
+						break;
+					case "false":
+						state.option.latedef = false;
+						break;
+					case "nofunc":
+						state.option.latedef = "nofunc";
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				var match = /^([+-])(W\d{3})$/g.exec(key);
+				if (match) {
+					// ignore for -W..., unignore for +W...
+					state.ignored[match[2]] = (match[1] === "-");
+					return;
+				}
+
+				var tn;
+				if (val === "true" || val === "false") {
+					if (nt.type === "jslint") {
+						tn = renamedOptions[key] || key;
+						state.option[tn] = (val === "true");
+
+						if (invertedOptions[tn] !== undefined) {
+							state.option[tn] = !state.option[tn];
+						}
+					} else {
+						state.option[key] = (val === "true");
+					}
+
+					if (key === "newcap") {
+						state.option["(explicitNewcap)"] = true;
+					}
+					return;
+				}
+
+				error("E002", nt);
+			});
+
+			assume();
+		}
+	}
+
+	// We need a peek function. If it has an argument, it peeks that much farther
+	// ahead. It is used to distinguish
+	//	   for ( var i in ...
+	// from
+	//	   for ( var i = ...
+
+	function peek(p) {
+		var i = p || 0, j = 0, t;
+
+		while (j <= i) {
+			t = lookahead[j];
+			if (!t) {
+				t = lookahead[j] = lex.token();
+			}
+			j += 1;
+		}
+		return t;
+	}
+
+	// Produce the next token. It looks for programming errors.
+
+	function advance(id, t) {
+		switch (state.tokens.curr.id) {
+		case "(number)":
+			if (state.tokens.next.id === ".") {
+				warning("W005", state.tokens.curr);
+			}
+			break;
+		case "-":
+			if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
+				warning("W006");
+			}
+			break;
+		case "+":
+			if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
+				warning("W007");
+			}
+			break;
+		}
+
+		if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
+			anonname = state.tokens.curr.value;
+		}
+
+		if (id && state.tokens.next.id !== id) {
+			if (t) {
+				if (state.tokens.next.id === "(end)") {
+					error("E019", t, t.id);
+				} else {
+					error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
+				}
+			} else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
+				warning("W116", state.tokens.next, id, state.tokens.next.value);
+			}
+		}
+
+		state.tokens.prev = state.tokens.curr;
+		state.tokens.curr = state.tokens.next;
+		for (;;) {
+			state.tokens.next = lookahead.shift() || lex.token();
+
+			if (!state.tokens.next) { // No more tokens left, give up
+				quit("E041", state.tokens.curr.line);
+			}
+
+			if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
+				return;
+			}
+
+			if (state.tokens.next.check) {
+				state.tokens.next.check();
+			}
+
+			if (state.tokens.next.isSpecial) {
+				doOption();
+			} else {
+				if (state.tokens.next.id !== "(endline)") {
+					break;
+				}
+			}
+		}
+	}
+
+	// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
+	// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
+	// like .nud except that it is only used on the first token of a statement.
+	// Having .fud makes it much easier to define statement-oriented languages like
+	// JavaScript. I retained Pratt's nomenclature.
+
+	// .nud  Null denotation
+	// .fud  First null denotation
+	// .led  Left denotation
+	//  lbp  Left binding power
+	//  rbp  Right binding power
+
+	// They are elements of the parsing method called Top Down Operator Precedence.
+
+	function expression(rbp, initial) {
+		var left, isArray = false, isObject = false, isLetExpr = false;
+
+		// if current expression is a let expression
+		if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
+			if (!state.option.inMoz(true)) {
+				warning("W118", state.tokens.next, "let expressions");
+			}
+			isLetExpr = true;
+			// create a new block scope we use only for the current expression
+			funct["(blockscope)"].stack();
+			advance("let");
+			advance("(");
+			state.syntax["let"].fud.call(state.syntax["let"].fud, false);
+			advance(")");
+		}
+
+		if (state.tokens.next.id === "(end)")
+			error("E006", state.tokens.curr);
+
+		advance();
+
+		if (initial) {
+			anonname = "anonymous";
+			funct["(verb)"] = state.tokens.curr.value;
+		}
+
+		if (initial === true && state.tokens.curr.fud) {
+			left = state.tokens.curr.fud();
+		} else {
+			if (state.tokens.curr.nud) {
+				left = state.tokens.curr.nud();
+			} else {
+				error("E030", state.tokens.curr, state.tokens.curr.id);
+			}
+
+			var end_of_expr = state.tokens.next.identifier &&
+									!state.tokens.curr.led &&
+									state.tokens.curr.line !== state.tokens.next.line;
+			while (rbp < state.tokens.next.lbp && !end_of_expr) {
+				isArray = state.tokens.curr.value === "Array";
+				isObject = state.tokens.curr.value === "Object";
+
+				// #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
+				// Line breaks in IfStatement heads exist to satisfy the checkJSHint
+				// "Line too long." error.
+				if (left && (left.value || (left.first && left.first.value))) {
+					// If the left.value is not "new", or the left.first.value is a "."
+					// then safely assume that this is not "new Array()" and possibly
+					// not "new Object()"...
+					if (left.value !== "new" ||
+					  (left.first && left.first.value && left.first.value === ".")) {
+						isArray = false;
+						// ...In the case of Object, if the left.value and state.tokens.curr.value
+						// are not equal, then safely assume that this not "new Object()"
+						if (left.value !== state.tokens.curr.value) {
+							isObject = false;
+						}
+					}
+				}
+
+				advance();
+
+				if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+					warning("W009", state.tokens.curr);
+				}
+
+				if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+					warning("W010", state.tokens.curr);
+				}
+
+				if (left && state.tokens.curr.led) {
+					left = state.tokens.curr.led(left);
+				} else {
+					error("E033", state.tokens.curr, state.tokens.curr.id);
+				}
+			}
+		}
+		if (isLetExpr) {
+			funct["(blockscope)"].unstack();
+		}
+		return left;
+	}
+
+
+// Functions for conformance of style.
+
+	function adjacent(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white) {
+			if (left.character !== right.from && left.line === right.line) {
+				left.from += (left.character - left.from);
+				warning("W011", left, left.value);
+			}
+		}
+	}
+
+	function nobreak(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
+			warning("W012", right, right.value);
+		}
+	}
+
+	function nospace(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white && !left.comment) {
+			if (left.line === right.line) {
+				adjacent(left, right);
+			}
+		}
+	}
+
+	function nonadjacent(left, right) {
+		if (state.option.white) {
+			left = left || state.tokens.curr;
+			right = right || state.tokens.next;
+
+			if (left.value === ";" && right.value === ";") {
+				return;
+			}
+
+			if (left.line === right.line && left.character === right.from) {
+				left.from += (left.character - left.from);
+				warning("W013", left, left.value);
+			}
+		}
+	}
+
+	function nobreaknonadjacent(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (!state.option.laxbreak && left.line !== right.line) {
+			warning("W014", right, right.id);
+		} else if (state.option.white) {
+			left = left || state.tokens.curr;
+			right = right || state.tokens.next;
+			if (left.character === right.from) {
+				left.from += (left.character - left.from);
+				warning("W013", left, left.value);
+			}
+		}
+	}
+
+	function indentation(bias) {
+		if (!state.option.white && !state.option["(explicitIndent)"]) {
+			return;
+		}
+
+		if (state.tokens.next.id === "(end)") {
+			return;
+		}
+
+		var i = indent + (bias || 0);
+		if (state.tokens.next.from !== i) {
+			warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
+		}
+	}
+
+	function nolinebreak(t) {
+		t = t || state.tokens.curr;
+		if (t.line !== state.tokens.next.line) {
+			warning("E022", t, t.value);
+		}
+	}
+
+
+	function comma(opts) {
+		opts = opts || {};
+
+		if (!opts.peek) {
+			if (state.tokens.curr.line !== state.tokens.next.line) {
+				if (!state.option.laxcomma) {
+					if (comma.first) {
+						warning("I001");
+						comma.first = false;
+					}
+					warning("W014", state.tokens.curr, state.tokens.next.value);
+				}
+			} else if (!state.tokens.curr.comment &&
+					state.tokens.curr.character !== state.tokens.next.from && state.option.white) {
+				state.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);
+				warning("W011", state.tokens.curr, state.tokens.curr.value);
+			}
+
+			advance(",");
+		}
+
+		// TODO: This is a temporary solution to fight against false-positives in
+		// arrays and objects with trailing commas (see GH-363). The best solution
+		// would be to extract all whitespace rules out of parser.
+
+		if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
+			nonadjacent(state.tokens.curr, state.tokens.next);
+		}
+
+		if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
+			// Keywords that cannot follow a comma operator.
+			switch (state.tokens.next.value) {
+			case "break":
+			case "case":
+			case "catch":
+			case "continue":
+			case "default":
+			case "do":
+			case "else":
+			case "finally":
+			case "for":
+			case "if":
+			case "in":
+			case "instanceof":
+			case "return":
+			case "yield":
+			case "switch":
+			case "throw":
+			case "try":
+			case "var":
+			case "let":
+			case "while":
+			case "with":
+				error("E024", state.tokens.next, state.tokens.next.value);
+				return false;
+			}
+		}
+
+		if (state.tokens.next.type === "(punctuator)") {
+			switch (state.tokens.next.value) {
+			case "}":
+			case "]":
+			case ",":
+				if (opts.allowTrailing) {
+					return true;
+				}
+
+				/* falls through */
+			case ")":
+				error("E024", state.tokens.next, state.tokens.next.value);
+				return false;
+			}
+		}
+		return true;
+	}
+
+	// Functional constructors for making the symbols that will be inherited by
+	// tokens.
+
+	function symbol(s, p) {
+		var x = state.syntax[s];
+		if (!x || typeof x !== "object") {
+			state.syntax[s] = x = {
+				id: s,
+				lbp: p,
+				value: s
+			};
+		}
+		return x;
+	}
+
+	function delim(s) {
+		return symbol(s, 0);
+	}
+
+	function stmt(s, f) {
+		var x = delim(s);
+		x.identifier = x.reserved = true;
+		x.fud = f;
+		return x;
+	}
+
+	function blockstmt(s, f) {
+		var x = stmt(s, f);
+		x.block = true;
+		return x;
+	}
+
+	function reserveName(x) {
+		var c = x.id.charAt(0);
+		if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
+			x.identifier = x.reserved = true;
+		}
+		return x;
+	}
+
+	function prefix(s, f) {
+		var x = symbol(s, 150);
+		reserveName(x);
+		x.nud = (typeof f === "function") ? f : function () {
+			this.right = expression(150);
+			this.arity = "unary";
+			if (this.id === "++" || this.id === "--") {
+				if (state.option.plusplus) {
+					warning("W016", this, this.id);
+				} else if ((!this.right.identifier || isReserved(this.right)) &&
+						this.right.id !== "." && this.right.id !== "[") {
+					warning("W017", this);
+				}
+			}
+			return this;
+		};
+		return x;
+	}
+
+	function type(s, f) {
+		var x = delim(s);
+		x.type = s;
+		x.nud = f;
+		return x;
+	}
+
+	function reserve(name, func) {
+		var x = type(name, func);
+		x.identifier = true;
+		x.reserved = true;
+		return x;
+	}
+
+	function FutureReservedWord(name, meta) {
+		var x = type(name, (meta && meta.nud) || function () {
+			return this;
+		});
+
+		meta = meta || {};
+		meta.isFutureReservedWord = true;
+
+		x.value = name;
+		x.identifier = true;
+		x.reserved = true;
+		x.meta = meta;
+
+		return x;
+	}
+
+	function reservevar(s, v) {
+		return reserve(s, function () {
+			if (typeof v === "function") {
+				v(this);
+			}
+			return this;
+		});
+	}
+
+	function infix(s, f, p, w) {
+		var x = symbol(s, p);
+		reserveName(x);
+		x.led = function (left) {
+			if (!w) {
+				nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+				nonadjacent(state.tokens.curr, state.tokens.next);
+			}
+			if (s === "in" && left.id === "!") {
+				warning("W018", left, "!");
+			}
+			if (typeof f === "function") {
+				return f(left, this);
+			} else {
+				this.left = left;
+				this.right = expression(p);
+				return this;
+			}
+		};
+		return x;
+	}
+
+
+	function application(s) {
+		var x = symbol(s, 42);
+
+		x.led = function (left) {
+			if (!state.option.inESNext()) {
+				warning("W104", state.tokens.curr, "arrow function syntax (=>)");
+			}
+
+			nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+
+			this.left = left;
+			this.right = doFunction(undefined, undefined, false, left);
+			return this;
+		};
+		return x;
+	}
+
+	function relation(s, f) {
+		var x = symbol(s, 100);
+
+		x.led = function (left) {
+			nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+			var right = expression(100);
+
+			if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
+				warning("W019", this);
+			} else if (f) {
+				f.apply(this, [left, right]);
+			}
+
+			if (!left || !right) {
+				quit("E041", state.tokens.curr.line);
+			}
+
+			if (left.id === "!") {
+				warning("W018", left, "!");
+			}
+
+			if (right.id === "!") {
+				warning("W018", right, "!");
+			}
+
+			this.left = left;
+			this.right = right;
+			return this;
+		};
+		return x;
+	}
+
+	function isPoorRelation(node) {
+		return node &&
+			  ((node.type === "(number)" && +node.value === 0) ||
+			   (node.type === "(string)" && node.value === "") ||
+			   (node.type === "null" && !state.option.eqnull) ||
+				node.type === "true" ||
+				node.type === "false" ||
+				node.type === "undefined");
+	}
+
+	function assignop(s) {
+		symbol(s, 20).exps = true;
+
+		return infix(s, function (left, that) {
+			that.left = left;
+
+			if (left) {
+				if (predefined[left.value] === false &&
+						scope[left.value]["(global)"] === true) {
+					warning("W020", left);
+				} else if (left["function"]) {
+					warning("W021", left, left.value);
+				}
+
+				if (funct[left.value] === "const") {
+					error("E013", left, left.value);
+				}
+
+				if (left.id === ".") {
+					if (!left.left) {
+						warning("E031", that);
+					} else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+						warning("E031", that);
+					}
+
+					that.right = expression(19);
+					return that;
+				} else if (left.id === "[") {
+					if (state.tokens.curr.left.first) {
+						state.tokens.curr.left.first.forEach(function (t) {
+							if (funct[t.value] === "const") {
+								error("E013", t, t.value);
+							}
+						});
+					} else if (!left.left) {
+						warning("E031", that);
+					} else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+						warning("E031", that);
+					}
+					that.right = expression(19);
+					return that;
+				} else if (left.identifier && !isReserved(left)) {
+					if (funct[left.value] === "exception") {
+						warning("W022", left);
+					}
+					that.right = expression(19);
+					return that;
+				}
+
+				if (left === state.syntax["function"]) {
+					warning("W023", state.tokens.curr);
+				}
+			}
+
+			error("E031", that);
+		}, 20);
+	}
+
+
+	function bitwise(s, f, p) {
+		var x = symbol(s, p);
+		reserveName(x);
+		x.led = (typeof f === "function") ? f : function (left) {
+			if (state.option.bitwise) {
+				warning("W016", this, this.id);
+			}
+			this.left = left;
+			this.right = expression(p);
+			return this;
+		};
+		return x;
+	}
+
+
+	function bitwiseassignop(s) {
+		symbol(s, 20).exps = true;
+		return infix(s, function (left, that) {
+			if (state.option.bitwise) {
+				warning("W016", that, that.id);
+			}
+			nonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+			if (left) {
+				if (left.id === "." || left.id === "[" ||
+						(left.identifier && !isReserved(left))) {
+					expression(19);
+					return that;
+				}
+				if (left === state.syntax["function"]) {
+					warning("W023", state.tokens.curr);
+				}
+				return that;
+			}
+			error("E031", that);
+		}, 20);
+	}
+
+
+	function suffix(s) {
+		var x = symbol(s, 150);
+
+		x.led = function (left) {
+			if (state.option.plusplus) {
+				warning("W016", this, this.id);
+			} else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
+				warning("W017", this);
+			}
+
+			this.left = left;
+			return this;
+		};
+		return x;
+	}
+
+	// fnparam means that this identifier is being defined as a function
+	// argument (see identifier())
+	// prop means that this identifier is that of an object property
+
+	function optionalidentifier(fnparam, prop) {
+		if (!state.tokens.next.identifier) {
+			return;
+		}
+
+		advance();
+
+		var curr = state.tokens.curr;
+		var meta = curr.meta || {};
+		var val  = state.tokens.curr.value;
+
+		if (!isReserved(curr)) {
+			return val;
+		}
+
+		if (prop) {
+			if (state.option.inES5() || meta.isFutureReservedWord) {
+				return val;
+			}
+		}
+
+		if (fnparam && val === "undefined") {
+			return val;
+		}
+
+		// Display an info message about reserved words as properties
+		// and ES5 but do it only once.
+		if (prop && !api.getCache("displayed:I002")) {
+			api.setCache("displayed:I002", true);
+			warning("I002");
+		}
+
+		warning("W024", state.tokens.curr, state.tokens.curr.id);
+		return val;
+	}
+
+	// fnparam means that this identifier is being defined as a function
+	// argument
+	// prop means that this identifier is that of an object property
+	function identifier(fnparam, prop) {
+		var i = optionalidentifier(fnparam, prop);
+		if (i) {
+			return i;
+		}
+		if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
+			warning("W025");
+		} else {
+			error("E030", state.tokens.next, state.tokens.next.value);
+		}
+	}
+
+
+	function reachable(s) {
+		var i = 0, t;
+		if (state.tokens.next.id !== ";" || noreach) {
+			return;
+		}
+		for (;;) {
+			t = peek(i);
+			if (t.reach) {
+				return;
+			}
+			if (t.id !== "(endline)") {
+				if (t.id === "function") {
+					if (!state.option.latedef) {
+						break;
+					}
+
+					warning("W026", t);
+					break;
+				}
+
+				warning("W027", t, t.value, s);
+				break;
+			}
+			i += 1;
+		}
+	}
+
+
+	function statement(noindent) {
+		var values;
+		var i = indent, r, s = scope, t = state.tokens.next;
+
+		if (t.id === ";") {
+			advance(";");
+			return;
+		}
+
+		// Is this a labelled statement?
+		var res = isReserved(t);
+
+		// We're being more tolerant here: if someone uses
+		// a FutureReservedWord as a label, we warn but proceed
+		// anyway.
+
+		if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
+			warning("W024", t, t.id);
+			res = false;
+		}
+
+		// detect a destructuring assignment
+		if (_.has(["[", "{"], t.value)) {
+			if (lookupBlockType().isDestAssign) {
+				if (!state.option.inESNext()) {
+					warning("W104", state.tokens.curr, "destructuring expression");
+				}
+				values = destructuringExpression();
+				values.forEach(function (tok) {
+					isundef(funct, "W117", tok.token, tok.id);
+				});
+				advance("=");
+				destructuringExpressionMatch(values, expression(5, true));
+				advance(";");
+				return;
+			}
+		}
+		if (t.identifier && !res && peek().id === ":") {
+			advance();
+			advance(":");
+			scope = Object.create(s);
+			addlabel(t.value, "label");
+
+			if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
+				warning("W028", state.tokens.next, t.value, state.tokens.next.value);
+			}
+
+			state.tokens.next.label = t.value;
+			t = state.tokens.next;
+		}
+
+		// Is it a lonely block?
+
+		if (t.id === "{") {
+	                // Is it a switch case block?
+	                //
+	                //      switch (foo) {
+	                //              case bar: { <= here.
+	                //                      ...
+	                //              }
+	                //      }
+	                var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
+	                block(true, true, false, false, iscase);
+			return;
+		}
+
+		// Parse the statement.
+
+		if (!noindent) {
+			indentation();
+		}
+		r = expression(0, true);
+
+		// Look for the final semicolon.
+
+		if (!t.block) {
+			if (!state.option.expr && (!r || !r.exps)) {
+				warning("W030", state.tokens.curr);
+			} else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
+				warning("W031", t);
+			}
+
+			if (state.tokens.next.id !== ";") {
+				if (!state.option.asi) {
+					// If this is the last statement in a block that ends on
+					// the same line *and* option lastsemic is on, ignore the warning.
+					// Otherwise, complain about missing semicolon.
+					if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
+						state.tokens.next.line !== state.tokens.curr.line) {
+						warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
+					}
+				}
+			} else {
+				adjacent(state.tokens.curr, state.tokens.next);
+				advance(";");
+				nonadjacent(state.tokens.curr, state.tokens.next);
+			}
+		}
+
+		// Restore the indentation.
+
+		indent = i;
+		scope = s;
+		return r;
+	}
+
+
+	function statements(startLine) {
+		var a = [], p;
+
+		while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
+			if (state.tokens.next.id === ";") {
+				p = peek();
+
+				if (!p || (p.id !== "(" && p.id !== "[")) {
+					warning("W032");
+				}
+
+				advance(";");
+			} else {
+				a.push(statement(startLine === state.tokens.next.line));
+			}
+		}
+		return a;
+	}
+
+
+	/*
+	 * read all directives
+	 * recognizes a simple form of asi, but always
+	 * warns, if it is used
+	 */
+	function directives() {
+		var i, p, pn;
+
+		for (;;) {
+			if (state.tokens.next.id === "(string)") {
+				p = peek(0);
+				if (p.id === "(endline)") {
+					i = 1;
+					do {
+						pn = peek(i);
+						i = i + 1;
+					} while (pn.id === "(endline)");
+
+					if (pn.id !== ";") {
+						if (pn.id !== "(string)" && pn.id !== "(number)" &&
+							pn.id !== "(regexp)" && pn.identifier !== true &&
+							pn.id !== "}") {
+							break;
+						}
+						warning("W033", state.tokens.next);
+					} else {
+						p = pn;
+					}
+				} else if (p.id === "}") {
+					// Directive with no other statements, warn about missing semicolon
+					warning("W033", p);
+				} else if (p.id !== ";") {
+					break;
+				}
+
+				indentation();
+				advance();
+				if (state.directive[state.tokens.curr.value]) {
+					warning("W034", state.tokens.curr, state.tokens.curr.value);
+				}
+
+				if (state.tokens.curr.value === "use strict") {
+					if (!state.option["(explicitNewcap)"])
+						state.option.newcap = true;
+					state.option.undef = true;
+				}
+
+				// there's no directive negation, so always set to true
+				state.directive[state.tokens.curr.value] = true;
+
+				if (p.id === ";") {
+					advance(";");
+				}
+				continue;
+			}
+			break;
+		}
+	}
+
+
+	/*
+	 * Parses a single block. A block is a sequence of statements wrapped in
+	 * braces.
+	 *
+	 * ordinary     - true for everything but function bodies and try blocks.
+	 * stmt         - true if block can be a single statement (e.g. in if/for/while).
+	 * isfunc       - true if block is a function body
+	 * isfatarrow   -
+	 * iscase       - true if block is a switch case block
+	 */
+	function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
+		var a,
+			b = inblock,
+			old_indent = indent,
+			m,
+			s = scope,
+			t,
+			line,
+			d;
+
+		inblock = ordinary;
+
+		if (!ordinary || !state.option.funcscope)
+			scope = Object.create(scope);
+
+		nonadjacent(state.tokens.curr, state.tokens.next);
+		t = state.tokens.next;
+
+		var metrics = funct["(metrics)"];
+		metrics.nestedBlockDepth += 1;
+		metrics.verifyMaxNestedBlockDepthPerFunction();
+
+		if (state.tokens.next.id === "{") {
+			advance("{");
+
+			// create a new block scope
+			funct["(blockscope)"].stack();
+
+			line = state.tokens.curr.line;
+			if (state.tokens.next.id !== "}") {
+				indent += state.option.indent;
+				while (!ordinary && state.tokens.next.from > indent) {
+					indent += state.option.indent;
+				}
+
+				if (isfunc) {
+					m = {};
+					for (d in state.directive) {
+						if (_.has(state.directive, d)) {
+							m[d] = state.directive[d];
+						}
+					}
+					directives();
+
+					if (state.option.strict && funct["(context)"]["(global)"]) {
+						if (!m["use strict"] && !state.directive["use strict"]) {
+							warning("E007");
+						}
+					}
+				}
+
+				a = statements(line);
+
+				metrics.statementCount += a.length;
+
+				if (isfunc) {
+					state.directive = m;
+				}
+
+				indent -= state.option.indent;
+				if (line !== state.tokens.next.line) {
+					indentation();
+				}
+			} else if (line !== state.tokens.next.line) {
+				indentation();
+			}
+			advance("}", t);
+
+			funct["(blockscope)"].unstack();
+
+			indent = old_indent;
+		} else if (!ordinary) {
+			if (isfunc) {
+				m = {};
+				if (stmt && !isfatarrow && !state.option.inMoz(true)) {
+					error("W118", state.tokens.curr, "function closure expressions");
+				}
+
+				if (!stmt) {
+					for (d in state.directive) {
+						if (_.has(state.directive, d)) {
+							m[d] = state.directive[d];
+						}
+					}
+				}
+				expression(5);
+
+				if (state.option.strict && funct["(context)"]["(global)"]) {
+					if (!m["use strict"] && !state.directive["use strict"]) {
+						warning("E007");
+					}
+				}
+			} else {
+				error("E021", state.tokens.next, "{", state.tokens.next.value);
+			}
+		} else {
+
+			// check to avoid let declaration not within a block
+			funct["(nolet)"] = true;
+
+			if (!stmt || state.option.curly) {
+				warning("W116", state.tokens.next, "{", state.tokens.next.value);
+			}
+
+			noreach = true;
+			indent += state.option.indent;
+			// test indentation only if statement is in new line
+			a = [statement(state.tokens.next.line === state.tokens.curr.line)];
+			indent -= state.option.indent;
+			noreach = false;
+
+			delete funct["(nolet)"];
+		}
+		// If it is a "break" in switch case, don't clear and let it propagate out.
+		if (!(iscase && funct["(verb)"] === "break")) funct["(verb)"] = null;
+
+		if (!ordinary || !state.option.funcscope) scope = s;
+		inblock = b;
+		if (ordinary && state.option.noempty && (!a || a.length === 0)) {
+			warning("W035");
+		}
+		metrics.nestedBlockDepth -= 1;
+		return a;
+	}
+
+
+	function countMember(m) {
+		if (membersOnly && typeof membersOnly[m] !== "boolean") {
+			warning("W036", state.tokens.curr, m);
+		}
+		if (typeof member[m] === "number") {
+			member[m] += 1;
+		} else {
+			member[m] = 1;
+		}
+	}
+
+
+	function note_implied(tkn) {
+		var name = tkn.value, line = tkn.line, a = implied[name];
+		if (typeof a === "function") {
+			a = false;
+		}
+
+		if (!a) {
+			a = [line];
+			implied[name] = a;
+		} else if (a[a.length - 1] !== line) {
+			a.push(line);
+		}
+	}
+
+
+	// Build the syntax table by declaring the syntactic elements of the language.
+
+	type("(number)", function () {
+		return this;
+	});
+
+	type("(string)", function () {
+		return this;
+	});
+
+	state.syntax["(identifier)"] = {
+		type: "(identifier)",
+		lbp: 0,
+		identifier: true,
+		nud: function () {
+			var v = this.value,
+				s = scope[v],
+				f;
+
+			if (typeof s === "function") {
+				// Protection against accidental inheritance.
+				s = undefined;
+			} else if (typeof s === "boolean") {
+				f = funct;
+				funct = functions[0];
+				addlabel(v, "var");
+				s = funct;
+				funct = f;
+			}
+			var block;
+			if (_.has(funct, "(blockscope)")) {
+				block = funct["(blockscope)"].getlabel(v);
+			}
+
+			// The name is in scope and defined in the current function.
+			if (funct === s || block) {
+				// Change 'unused' to 'var', and reject labels.
+				// the name is in a block scope
+				switch (block ? block[v]["(type)"] : funct[v]) {
+				case "unused":
+					if (block) block[v]["(type)"] = "var";
+					else funct[v] = "var";
+					break;
+				case "unction":
+					if (block) block[v]["(type)"] = "function";
+					else funct[v] = "function";
+					this["function"] = true;
+					break;
+				case "function":
+					this["function"] = true;
+					break;
+				case "label":
+					warning("W037", state.tokens.curr, v);
+					break;
+				}
+			} else if (funct["(global)"]) {
+				// The name is not defined in the function.  If we are in the global
+				// scope, then we have an undefined variable.
+				//
+				// Operators typeof and delete do not raise runtime errors even if
+				// the base object of a reference is null so no need to display warning
+				// if we're inside of typeof or delete.
+
+				if (typeof predefined[v] !== "boolean") {
+					// Attempting to subscript a null reference will throw an
+					// error, even within the typeof and delete operators
+					if (!(anonname === "typeof" || anonname === "delete") ||
+						(state.tokens.next && (state.tokens.next.value === "." ||
+							state.tokens.next.value === "["))) {
+
+						// if we're in a list comprehension, variables are declared
+						// locally and used before being defined. So we check
+						// the presence of the given variable in the comp array
+						// before declaring it undefined.
+
+						if (!funct["(comparray)"].check(v)) {
+							isundef(funct, "W117", state.tokens.curr, v);
+						}
+					}
+				}
+
+				note_implied(state.tokens.curr);
+			} else {
+				// If the name is already defined in the current
+				// function, but not as outer, then there is a scope error.
+
+				switch (funct[v]) {
+				case "closure":
+				case "function":
+				case "var":
+				case "unused":
+					warning("W038", state.tokens.curr, v);
+					break;
+				case "label":
+					warning("W037", state.tokens.curr, v);
+					break;
+				case "outer":
+				case "global":
+					break;
+				default:
+					// If the name is defined in an outer function, make an outer entry,
+					// and if it was unused, make it var.
+					if (s === true) {
+						funct[v] = true;
+					} else if (s === null) {
+						warning("W039", state.tokens.curr, v);
+						note_implied(state.tokens.curr);
+					} else if (typeof s !== "object") {
+						// Operators typeof and delete do not raise runtime errors even
+						// if the base object of a reference is null so no need to
+						//
+						// display warning if we're inside of typeof or delete.
+						// Attempting to subscript a null reference will throw an
+						// error, even within the typeof and delete operators
+						if (!(anonname === "typeof" || anonname === "delete") ||
+							(state.tokens.next &&
+								(state.tokens.next.value === "." || state.tokens.next.value === "["))) {
+
+							isundef(funct, "W117", state.tokens.curr, v);
+						}
+						funct[v] = true;
+						note_implied(state.tokens.curr);
+					} else {
+						switch (s[v]) {
+						case "function":
+						case "unction":
+							this["function"] = true;
+							s[v] = "closure";
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "var":
+						case "unused":
+							s[v] = "closure";
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "closure":
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "label":
+							warning("W037", state.tokens.curr, v);
+						}
+					}
+				}
+			}
+			return this;
+		},
+		led: function () {
+			error("E033", state.tokens.next, state.tokens.next.value);
+		}
+	};
+
+	type("(regexp)", function () {
+		return this;
+	});
+
+	// ECMAScript parser
+
+	delim("(endline)");
+	delim("(begin)");
+	delim("(end)").reach = true;
+	delim("(error)").reach = true;
+	delim("}").reach = true;
+	delim(")");
+	delim("]");
+	delim("\"").reach = true;
+	delim("'").reach = true;
+	delim(";");
+	delim(":").reach = true;
+	delim("#");
+
+	reserve("else");
+	reserve("case").reach = true;
+	reserve("catch");
+	reserve("default").reach = true;
+	reserve("finally");
+	reservevar("arguments", function (x) {
+		if (state.directive["use strict"] && funct["(global)"]) {
+			warning("E008", x);
+		}
+	});
+	reservevar("eval");
+	reservevar("false");
+	reservevar("Infinity");
+	reservevar("null");
+	reservevar("this", function (x) {
+		if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
+				funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
+			warning("W040", x);
+		}
+	});
+	reservevar("true");
+	reservevar("undefined");
+
+	assignop("=", "assign", 20);
+	assignop("+=", "assignadd", 20);
+	assignop("-=", "assignsub", 20);
+	assignop("*=", "assignmult", 20);
+	assignop("/=", "assigndiv", 20).nud = function () {
+		error("E014");
+	};
+	assignop("%=", "assignmod", 20);
+
+	bitwiseassignop("&=", "assignbitand", 20);
+	bitwiseassignop("|=", "assignbitor", 20);
+	bitwiseassignop("^=", "assignbitxor", 20);
+	bitwiseassignop("<<=", "assignshiftleft", 20);
+	bitwiseassignop(">>=", "assignshiftright", 20);
+	bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
+	infix(",", function (left, that) {
+		var expr;
+		that.exprs = [left];
+		if (!comma({peek: true})) {
+			return that;
+		}
+		while (true) {
+			if (!(expr = expression(5)))  {
+				break;
+			}
+			that.exprs.push(expr);
+			if (state.tokens.next.value !== "," || !comma()) {
+				break;
+			}
+		}
+		return that;
+	}, 5, true);
+	infix("?", function (left, that) {
+		that.left = left;
+		that.right = expression(10);
+		advance(":");
+		that["else"] = expression(10);
+		return that;
+	}, 30);
+
+	infix("||", "or", 40);
+	infix("&&", "and", 50);
+	bitwise("|", "bitor", 70);
+	bitwise("^", "bitxor", 80);
+	bitwise("&", "bitand", 90);
+	relation("==", function (left, right) {
+		var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
+
+		if (!eqnull && state.option.eqeqeq)
+			warning("W116", this, "===", "==");
+		else if (isPoorRelation(left))
+			warning("W041", this, "===", left.value);
+		else if (isPoorRelation(right))
+			warning("W041", this, "===", right.value);
+
+		return this;
+	});
+	relation("===");
+	relation("!=", function (left, right) {
+		var eqnull = state.option.eqnull &&
+				(left.value === "null" || right.value === "null");
+
+		if (!eqnull && state.option.eqeqeq) {
+			warning("W116", this, "!==", "!=");
+		} else if (isPoorRelation(left)) {
+			warning("W041", this, "!==", left.value);
+		} else if (isPoorRelation(right)) {
+			warning("W041", this, "!==", right.value);
+		}
+		return this;
+	});
+	relation("!==");
+	relation("<");
+	relation(">");
+	relation("<=");
+	relation(">=");
+	bitwise("<<", "shiftleft", 120);
+	bitwise(">>", "shiftright", 120);
+	bitwise(">>>", "shiftrightunsigned", 120);
+	infix("in", "in", 120);
+	infix("instanceof", "instanceof", 120);
+	infix("+", function (left, that) {
+		var right = expression(130);
+		if (left && right && left.id === "(string)" && right.id === "(string)") {
+			left.value += right.value;
+			left.character = right.character;
+			if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
+				warning("W050", left);
+			}
+			return left;
+		}
+		that.left = left;
+		that.right = right;
+		return that;
+	}, 130);
+	prefix("+", "num");
+	prefix("+++", function () {
+		warning("W007");
+		this.right = expression(150);
+		this.arity = "unary";
+		return this;
+	});
+	infix("+++", function (left) {
+		warning("W007");
+		this.left = left;
+		this.right = expression(130);
+		return this;
+	}, 130);
+	infix("-", "sub", 130);
+	prefix("-", "neg");
+	prefix("---", function () {
+		warning("W006");
+		this.right = expression(150);
+		this.arity = "unary";
+		return this;
+	});
+	infix("---", function (left) {
+		warning("W006");
+		this.left = left;
+		this.right = expression(130);
+		return this;
+	}, 130);
+	infix("*", "mult", 140);
+	infix("/", "div", 140);
+	infix("%", "mod", 140);
+
+	suffix("++", "postinc");
+	prefix("++", "preinc");
+	state.syntax["++"].exps = true;
+
+	suffix("--", "postdec");
+	prefix("--", "predec");
+	state.syntax["--"].exps = true;
+	prefix("delete", function () {
+		var p = expression(5);
+		if (!p || (p.id !== "." && p.id !== "[")) {
+			warning("W051");
+		}
+		this.first = p;
+		return this;
+	}).exps = true;
+
+	prefix("~", function () {
+		if (state.option.bitwise) {
+			warning("W052", this, "~");
+		}
+		expression(150);
+		return this;
+	});
+
+	prefix("...", function () {
+		if (!state.option.inESNext()) {
+			warning("W104", this, "spread/rest operator");
+		}
+		if (!state.tokens.next.identifier) {
+			error("E030", state.tokens.next, state.tokens.next.value);
+		}
+		expression(150);
+		return this;
+	});
+
+	prefix("!", function () {
+		this.right = expression(150);
+		this.arity = "unary";
+
+		if (!this.right) { // '!' followed by nothing? Give up.
+			quit("E041", this.line || 0);
+		}
+
+		if (bang[this.right.id] === true) {
+			warning("W018", this, "!");
+		}
+		return this;
+	});
+
+	prefix("typeof", "typeof");
+	prefix("new", function () {
+		var c = expression(155), i;
+		if (c && c.id !== "function") {
+			if (c.identifier) {
+				c["new"] = true;
+				switch (c.value) {
+				case "Number":
+				case "String":
+				case "Boolean":
+				case "Math":
+				case "JSON":
+					warning("W053", state.tokens.prev, c.value);
+					break;
+				case "Function":
+					if (!state.option.evil) {
+						warning("W054");
+					}
+					break;
+				case "Date":
+				case "RegExp":
+					break;
+				default:
+					if (c.id !== "function") {
+						i = c.value.substr(0, 1);
+						if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
+							warning("W055", state.tokens.curr);
+						}
+					}
+				}
+			} else {
+				if (c.id !== "." && c.id !== "[" && c.id !== "(") {
+					warning("W056", state.tokens.curr);
+				}
+			}
+		} else {
+			if (!state.option.supernew)
+				warning("W057", this);
+		}
+		adjacent(state.tokens.curr, state.tokens.next);
+		if (state.tokens.next.id !== "(" && !state.option.supernew) {
+			warning("W058", state.tokens.curr, state.tokens.curr.value);
+		}
+		this.first = c;
+		return this;
+	});
+	state.syntax["new"].exps = true;
+
+	prefix("void").exps = true;
+
+	infix(".", function (left, that) {
+		adjacent(state.tokens.prev, state.tokens.curr);
+		nobreak();
+		var m = identifier(false, true);
+
+		if (typeof m === "string") {
+			countMember(m);
+		}
+
+		that.left = left;
+		that.right = m;
+
+		if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
+			warning("W001");
+		}
+
+		if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
+			if (state.option.noarg)
+				warning("W059", left, m);
+			else if (state.directive["use strict"])
+				error("E008");
+		} else if (!state.option.evil && left && left.value === "document" &&
+				(m === "write" || m === "writeln")) {
+			warning("W060", left);
+		}
+
+		if (!state.option.evil && (m === "eval" || m === "execScript")) {
+			warning("W061");
+		}
+
+		return that;
+	}, 160, true);
+
+	infix("(", function (left, that) {
+		if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
+			nobreak(state.tokens.prev, state.tokens.curr);
+		}
+
+		nospace();
+		if (state.option.immed && left && !left.immed && left.id === "function") {
+			warning("W062");
+		}
+
+		var n = 0;
+		var p = [];
+
+		if (left) {
+			if (left.type === "(identifier)") {
+				if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
+					if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
+						if (left.value === "Math") {
+							warning("W063", left);
+						} else if (state.option.newcap) {
+							warning("W064", left);
+						}
+					}
+				}
+			}
+		}
+
+		if (state.tokens.next.id !== ")") {
+			for (;;) {
+				p[p.length] = expression(10);
+				n += 1;
+				if (state.tokens.next.id !== ",") {
+					break;
+				}
+				comma();
+			}
+		}
+
+		advance(")");
+		nospace(state.tokens.prev, state.tokens.curr);
+
+		if (typeof left === "object") {
+			if (left.value === "parseInt" && n === 1) {
+				warning("W065", state.tokens.curr);
+			}
+			if (!state.option.evil) {
+				if (left.value === "eval" || left.value === "Function" ||
+						left.value === "execScript") {
+					warning("W061", left);
+
+					if (p[0] && [0].id === "(string)") {
+						addInternalSrc(left, p[0].value);
+					}
+				} else if (p[0] && p[0].id === "(string)" &&
+					   (left.value === "setTimeout" ||
+						left.value === "setInterval")) {
+					warning("W066", left);
+					addInternalSrc(left, p[0].value);
+
+				// window.setTimeout/setInterval
+				} else if (p[0] && p[0].id === "(string)" &&
+					   left.value === "." &&
+					   left.left.value === "window" &&
+					   (left.right === "setTimeout" ||
+						left.right === "setInterval")) {
+					warning("W066", left);
+					addInternalSrc(left, p[0].value);
+				}
+			}
+			if (!left.identifier && left.id !== "." && left.id !== "[" &&
+					left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
+					left.id !== "?") {
+				warning("W067", left);
+			}
+		}
+
+		that.left = left;
+		return that;
+	}, 155, true).exps = true;
+
+	prefix("(", function () {
+		nospace();
+		var bracket, brackets = [];
+		var pn, pn1, i = 0;
+
+		do {
+			pn = peek(i);
+			i += 1;
+			pn1 = peek(i);
+			i += 1;
+		} while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
+
+		if (state.tokens.next.id === "function") {
+			state.tokens.next.immed = true;
+		}
+
+		var exprs = [];
+
+		if (state.tokens.next.id !== ")") {
+			for (;;) {
+				if (pn1.value === "=>" && state.tokens.next.value === "{") {
+					bracket = state.tokens.next;
+					bracket.left = destructuringExpression();
+					brackets.push(bracket);
+					for (var t in bracket.left) {
+						exprs.push(bracket.left[t].token);
+					}
+				} else {
+					exprs.push(expression(5));
+				}
+				if (state.tokens.next.id !== ",") {
+					break;
+				}
+				comma();
+			}
+		}
+
+		advance(")", this);
+		nospace(state.tokens.prev, state.tokens.curr);
+		if (state.option.immed && exprs[0] && exprs[0].id === "function") {
+			if (state.tokens.next.id !== "(" &&
+			  (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
+				warning("W068", this);
+			}
+		}
+
+		if (state.tokens.next.value === "=>") {
+			return exprs;
+		}
+		if (!exprs.length) {
+			return;
+		}
+		exprs[exprs.length - 1].paren = true;
+		if (exprs.length > 1) {
+			return Object.create(state.syntax[","], { exprs: { value: exprs } });
+		}
+		return exprs[0];
+	});
+
+	application("=>");
+
+	infix("[", function (left, that) {
+		nobreak(state.tokens.prev, state.tokens.curr);
+		nospace();
+		var e = expression(5), s;
+		if (e && e.type === "(string)") {
+			if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
+				warning("W061", that);
+			}
+
+			countMember(e.value);
+			if (!state.option.sub && reg.identifier.test(e.value)) {
+				s = state.syntax[e.value];
+				if (!s || !isReserved(s)) {
+					warning("W069", state.tokens.prev, e.value);
+				}
+			}
+		}
+		advance("]", that);
+
+		if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
+			warning("W001");
+		}
+
+		nospace(state.tokens.prev, state.tokens.curr);
+		that.left = left;
+		that.right = e;
+		return that;
+	}, 160, true);
+
+	function comprehensiveArrayExpression() {
+		var res = {};
+		res.exps = true;
+		funct["(comparray)"].stack();
+
+		res.right = expression(5);
+		advance("for");
+		if (state.tokens.next.value === "each") {
+			advance("each");
+			if (!state.option.inMoz(true)) {
+				warning("W118", state.tokens.curr, "for each");
+			}
+		}
+		advance("(");
+		funct["(comparray)"].setState("define");
+		res.left = expression(5);
+		advance(")");
+		if (state.tokens.next.value === "if") {
+			advance("if");
+			advance("(");
+			funct["(comparray)"].setState("filter");
+			res.filter = expression(5);
+			advance(")");
+		}
+		advance("]");
+		funct["(comparray)"].unstack();
+		return res;
+	}
+
+	prefix("[", function () {
+		var blocktype = lookupBlockType(true);
+		if (blocktype.isCompArray) {
+			if (!state.option.inMoz(true)) {
+				warning("W118", state.tokens.curr, "array comprehension");
+			}
+			return comprehensiveArrayExpression();
+		} else if (blocktype.isDestAssign && !state.option.inESNext()) {
+			warning("W104", state.tokens.curr, "destructuring assignment");
+		}
+		var b = state.tokens.curr.line !== state.tokens.next.line;
+		this.first = [];
+		if (b) {
+			indent += state.option.indent;
+			if (state.tokens.next.from === indent + state.option.indent) {
+				indent += state.option.indent;
+			}
+		}
+		while (state.tokens.next.id !== "(end)") {
+			while (state.tokens.next.id === ",") {
+				if (!state.option.inES5())
+					warning("W070");
+				advance(",");
+			}
+			if (state.tokens.next.id === "]") {
+				break;
+			}
+			if (b && state.tokens.curr.line !== state.tokens.next.line) {
+				indentation();
+			}
+			this.first.push(expression(10));
+			if (state.tokens.next.id === ",") {
+				comma({ allowTrailing: true });
+				if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
+					warning("W070", state.tokens.curr);
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		if (b) {
+			indent -= state.option.indent;
+			indentation();
+		}
+		advance("]", this);
+		return this;
+	}, 160);
+
+
+	function property_name() {
+		var id = optionalidentifier(false, true);
+
+		if (!id) {
+			if (state.tokens.next.id === "(string)") {
+				id = state.tokens.next.value;
+				advance();
+			} else if (state.tokens.next.id === "(number)") {
+				id = state.tokens.next.value.toString();
+				advance();
+			}
+		}
+
+		if (id === "hasOwnProperty") {
+			warning("W001");
+		}
+
+		return id;
+	}
+
+
+	function functionparams(parsed) {
+		var curr, next;
+		var params = [];
+		var ident;
+		var tokens = [];
+		var t;
+
+		if (parsed) {
+			if (parsed instanceof Array) {
+				for (var i in parsed) {
+					curr = parsed[i];
+					if (_.contains(["{", "["], curr.id)) {
+						for (t in curr.left) {
+							t = tokens[t];
+							if (t.id) {
+								params.push(t.id);
+								addlabel(t.id, "unused", t.token);
+							}
+						}
+					} else if (curr.value === "...") {
+						if (!state.option.inESNext()) {
+							warning("W104", curr, "spread/rest operator");
+						}
+						continue;
+					} else {
+						addlabel(curr.value, "unused", curr);
+					}
+				}
+				return params;
+			} else {
+				if (parsed.identifier === true) {
+					addlabel(parsed.value, "unused", parsed);
+					return [parsed];
+				}
+			}
+		}
+
+		next = state.tokens.next;
+
+		advance("(");
+		nospace();
+
+		if (state.tokens.next.id === ")") {
+			advance(")");
+			return;
+		}
+
+		for (;;) {
+			if (_.contains(["{", "["], state.tokens.next.id)) {
+				tokens = destructuringExpression();
+				for (t in tokens) {
+					t = tokens[t];
+					if (t.id) {
+						params.push(t.id);
+						addlabel(t.id, "unused", t.token);
+					}
+				}
+			} else if (state.tokens.next.value === "...") {
+				if (!state.option.inESNext()) {
+					warning("W104", state.tokens.next, "spread/rest operator");
+				}
+				advance("...");
+				nospace();
+				ident = identifier(true);
+				params.push(ident);
+				addlabel(ident, "unused", state.tokens.curr);
+			} else {
+				ident = identifier(true);
+				params.push(ident);
+				addlabel(ident, "unused", state.tokens.curr);
+			}
+			if (state.tokens.next.id === ",") {
+				comma();
+			} else {
+				advance(")", next);
+				nospace(state.tokens.prev, state.tokens.curr);
+				return params;
+			}
+		}
+	}
+
+
+	function doFunction(name, statement, generator, fatarrowparams) {
+		var f;
+		var oldOption = state.option;
+		var oldIgnored = state.ignored;
+		var oldScope  = scope;
+
+		state.option = Object.create(state.option);
+		state.ignored = Object.create(state.ignored);
+		scope  = Object.create(scope);
+
+		funct = {
+			"(name)"      : name || "\"" + anonname + "\"",
+			"(line)"      : state.tokens.next.line,
+			"(character)" : state.tokens.next.character,
+			"(context)"   : funct,
+			"(breakage)"  : 0,
+			"(loopage)"   : 0,
+			"(metrics)"   : createMetrics(state.tokens.next),
+			"(scope)"     : scope,
+			"(statement)" : statement,
+			"(tokens)"    : {},
+			"(blockscope)": funct["(blockscope)"],
+			"(comparray)" : funct["(comparray)"]
+		};
+
+		if (generator) {
+			funct["(generator)"] = true;
+		}
+
+		f = funct;
+		state.tokens.curr.funct = funct;
+
+		functions.push(funct);
+
+		if (name) {
+			addlabel(name, "function");
+		}
+
+		funct["(params)"] = functionparams(fatarrowparams);
+
+		funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
+
+		block(false, true, true, fatarrowparams ? true:false);
+
+		if (generator && funct["(generator)"] !== "yielded") {
+			error("E047", state.tokens.curr);
+		}
+
+		funct["(metrics)"].verifyMaxStatementsPerFunction();
+		funct["(metrics)"].verifyMaxComplexityPerFunction();
+		funct["(unusedOption)"] = state.option.unused;
+
+		scope = oldScope;
+		state.option = oldOption;
+		state.ignored = oldIgnored;
+		funct["(last)"] = state.tokens.curr.line;
+		funct["(lastcharacter)"] = state.tokens.curr.character;
+		funct = funct["(context)"];
+
+		return f;
+	}
+
+	function createMetrics(functionStartToken) {
+		return {
+			statementCount: 0,
+			nestedBlockDepth: -1,
+			ComplexityCount: 1,
+			verifyMaxStatementsPerFunction: function () {
+				if (state.option.maxstatements &&
+					this.statementCount > state.option.maxstatements) {
+					warning("W071", functionStartToken, this.statementCount);
+				}
+			},
+
+			verifyMaxParametersPerFunction: function (params) {
+				params = params || [];
+
+				if (state.option.maxparams && params.length > state.option.maxparams) {
+					warning("W072", functionStartToken, params.length);
+				}
+			},
+
+			verifyMaxNestedBlockDepthPerFunction: function () {
+				if (state.option.maxdepth &&
+					this.nestedBlockDepth > 0 &&
+					this.nestedBlockDepth === state.option.maxdepth + 1) {
+					warning("W073", null, this.nestedBlockDepth);
+				}
+			},
+
+			verifyMaxComplexityPerFunction: function () {
+				var max = state.option.maxcomplexity;
+				var cc = this.ComplexityCount;
+				if (max && cc > max) {
+					warning("W074", functionStartToken, cc);
+				}
+			}
+		};
+	}
+
+	function increaseComplexityCount() {
+		funct["(metrics)"].ComplexityCount += 1;
+	}
+
+	// Parse assignments that were found instead of conditionals.
+	// For example: if (a = 1) { ... }
+
+	function checkCondAssignment(expr) {
+		var id = expr.id;
+		if (id === ",") {
+			expr = expr.exprs[expr.exprs.length - 1];
+			id = expr.id;
+		}
+		switch (id) {
+		case "=":
+		case "+=":
+		case "-=":
+		case "*=":
+		case "%=":
+		case "&=":
+		case "|=":
+		case "^=":
+		case "/=":
+			if (!expr.paren && !state.option.boss) {
+				warning("W084");
+			}
+		}
+	}
+
+
+	(function (x) {
+		x.nud = function (isclassdef) {
+			var b, f, i, p, t, g;
+			var props = {}; // All properties, including accessors
+			var tag = "";
+
+			function saveProperty(name, tkn) {
+				if (props[name] && _.has(props, name))
+					warning("W075", state.tokens.next, i);
+				else
+					props[name] = {};
+
+				props[name].basic = true;
+				props[name].basictkn = tkn;
+			}
+
+			function saveSetter(name, tkn) {
+				if (props[name] && _.has(props, name)) {
+					if (props[name].basic || props[name].setter)
+						warning("W075", state.tokens.next, i);
+				} else {
+					props[name] = {};
+				}
+
+				props[name].setter = true;
+				props[name].setterToken = tkn;
+			}
+
+			function saveGetter(name) {
+				if (props[name] && _.has(props, name)) {
+					if (props[name].basic || props[name].getter)
+						warning("W075", state.tokens.next, i);
+				} else {
+					props[name] = {};
+				}
+
+				props[name].getter = true;
+				props[name].getterToken = state.tokens.curr;
+			}
+
+			b = state.tokens.curr.line !== state.tokens.next.line;
+			if (b) {
+				indent += state.option.indent;
+				if (state.tokens.next.from === indent + state.option.indent) {
+					indent += state.option.indent;
+				}
+			}
+
+			for (;;) {
+				if (state.tokens.next.id === "}") {
+					break;
+				}
+
+				if (b) {
+					indentation();
+				}
+
+				if (isclassdef && state.tokens.next.value === "static") {
+					advance("static");
+					tag = "static ";
+				}
+
+				if (state.tokens.next.value === "get" && peek().id !== ":") {
+					advance("get");
+
+					if (!state.option.inES5(!isclassdef)) {
+						error("E034");
+					}
+
+					i = property_name();
+					if (!i) {
+						error("E035");
+					}
+
+					// It is a Syntax Error if PropName of MethodDefinition is
+					// "constructor" and SpecialMethod of MethodDefinition is true.
+					if (isclassdef && i === "constructor") {
+						error("E049", state.tokens.next, "class getter method", i);
+					}
+
+					saveGetter(tag + i);
+					t = state.tokens.next;
+					adjacent(state.tokens.curr, state.tokens.next);
+					f = doFunction();
+					p = f["(params)"];
+
+					if (p) {
+						warning("W076", t, p[0], i);
+					}
+
+					adjacent(state.tokens.curr, state.tokens.next);
+				} else if (state.tokens.next.value === "set" && peek().id !== ":") {
+					advance("set");
+
+					if (!state.option.inES5(!isclassdef)) {
+						error("E034");
+					}
+
+					i = property_name();
+					if (!i) {