Merge fx-team to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 04 Aug 2014 16:03:44 -0400
changeset 197503 25bf2f1664e91cc2192bb38aa825c80a5a758bd0
parent 197491 adb44e1f75599081eeffad443f8d87350717bb5e (current diff)
parent 197502 9595e2bb6f04e3dac1664f7c372f2db3d498f912 (diff)
child 197734 7f81be7db52884f813fd2d6ff2ae4fd0d8aeb452
push id27248
push userryanvm@gmail.com
push dateMon, 04 Aug 2014 20:03:52 +0000
treeherdermozilla-central@25bf2f1664e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge fx-team to m-c. a=merge
browser/components/loop/content/shared/libs/react-0.10.0.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1570,20 +1570,24 @@ pref("image.mem.max_decoded_image_kb", 2
 #ifndef RELEASE_BUILD
 pref("loop.enabled", true);
 #else
 pref("loop.enabled", false);
 #endif
 
 pref("loop.server", "https://loop.services.mozilla.com");
 pref("loop.seenToS", "unseen");
+pref("loop.legal.ToS_url", "https://accounts.firefox.com/legal/terms");
+pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/");
 pref("loop.do_not_disturb", false);
 pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
 pref("loop.retry_delay.start", 60000);
 pref("loop.retry_delay.limit", 300000);
+pref("loop.feedback.baseUrl", "https://input.mozilla.org/api/v1/feedback");
+pref("loop.feedback.product", "Loop");
 
 // serverURL to be assigned by services team
 pref("services.push.serverURL", "wss://push.services.mozilla.com/");
 
 pref("social.sidebar.unload_timeout_ms", 10000);
 
 pref("dom.identity.enabled", false);
 
--- a/browser/base/content/webrtcIndicator.js
+++ b/browser/base/content/webrtcIndicator.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-const Cu = Components.utils;
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/webrtcUI.jsm");
 
 const BUNDLE_URL = "chrome://browser/locale/webrtcIndicator.properties";
 let gStringBundle;
 
 function init(event) {
   gStringBundle = Services.strings.createBundle(BUNDLE_URL);
@@ -124,17 +124,22 @@ function onFirefoxButtonClick(event) {
 }
 
 let PositionHandler = {
   positionCustomized: false,
   threshold: 10,
   adjustPosition: function() {
     if (!this.positionCustomized) {
       // Center the window horizontally on the screen (not the available area).
-      window.moveTo((screen.width - document.documentElement.clientWidth) / 2, 0);
+      // Until we have moved the window to y=0, 'screen.width' may give a value
+      // for a secondary screen, so use values from the screen manager instead.
+      let width = {};
+      Cc["@mozilla.org/gfx/screenmanager;1"].getService(Ci.nsIScreenManager)
+        .primaryScreen.GetRectDisplayPix({}, {}, width, {});
+      window.moveTo((width.value - document.documentElement.clientWidth) / 2, 0);
     } else {
       // This will ensure we're at y=0.
       this.setXPosition(window.screenX);
     }
   },
   setXPosition: function(desiredX) {
     // Ensure the indicator isn't moved outside the available area of the screen.
     let desiredX = Math.max(desiredX, screen.availLeft);
--- a/browser/components/loop/content/conversation.html
+++ b/browser/components/loop/content/conversation.html
@@ -21,22 +21,23 @@
       window.OTProperties = {
         cdnURL: 'loop/',
       };
       window.OTProperties.assetURL = window.OTProperties.cdnURL + 'sdk-content/';
       window.OTProperties.configURL = window.OTProperties.assetURL + 'js/dynamic_config.min.js';
       window.OTProperties.cssURL = window.OTProperties.assetURL + 'css/ot.css';
     </script>
     <script type="text/javascript" src="loop/libs/sdk.js"></script>
-    <script type="text/javascript" src="loop/shared/libs/react-0.10.0.js"></script>
+    <script type="text/javascript" src="loop/shared/libs/react-0.11.1.js"></script>
     <script type="text/javascript" src="loop/shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="loop/shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="loop/shared/libs/backbone-1.1.2.js"></script>
 
     <script type="text/javascript" src="loop/shared/js/utils.js"></script>
     <script type="text/javascript" src="loop/shared/js/models.js"></script>
     <script type="text/javascript" src="loop/shared/js/router.js"></script>
     <script type="text/javascript" src="loop/shared/js/views.js"></script>
+    <script type="text/javascript" src="loop/shared/js/feedbackApiClient.js"></script>
     <script type="text/javascript" src="loop/js/client.js"></script>
     <script type="text/javascript" src="loop/js/desktopRouter.js"></script>
     <script type="text/javascript" src="loop/js/conversation.js"></script>
   </body>
 </html>
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -112,80 +112,56 @@ loop.conversation = (function(OT, mozL10
           )
         )
       );
       /* jshint ignore:end */
     }
   });
 
   /**
-   * Call ended view.
-   * @type {loop.shared.views.BaseView}
-   */
-  var EndedCallView = sharedViews.BaseView.extend({
-    template: _.template([
-      '<p>',
-      '  <button class="btn btn-info" data-l10n-id="close_window"></button>',
-      '</p>'
-    ].join("")),
-
-    className: "call-ended",
-
-    events: {
-      "click button": "closeWindow"
-    },
-
-    closeWindow: function(event) {
-      event.preventDefault();
-      // XXX For now, we just close the window.
-      window.close();
-    }
-  });
-
-  /**
    * Conversation router.
    *
    * Required options:
    * - {loop.shared.models.ConversationModel} conversation Conversation model.
    * - {loop.shared.components.Notifier}      notifier     Notifier component.
    *
    * @type {loop.shared.router.BaseConversationRouter}
    */
   var ConversationRouter = loop.desktopRouter.DesktopConversationRouter.extend({
     routes: {
       "incoming/:version": "incoming",
       "call/accept": "accept",
       "call/decline": "decline",
       "call/ongoing": "conversation",
-      "call/ended": "ended",
-      "call/declineAndBlock": "declineAndBlock"
+      "call/declineAndBlock": "declineAndBlock",
+      "call/feedback": "feedback"
     },
 
     /**
      * @override {loop.shared.router.BaseConversationRouter.startCall}
      */
     startCall: function() {
       this.navigate("call/ongoing", {trigger: true});
     },
 
     /**
      * @override {loop.shared.router.BaseConversationRouter.endCall}
      */
     endCall: function() {
-      this.navigate("call/ended", {trigger: true});
+      this.navigate("call/feedback", {trigger: true});
     },
 
     /**
      * Incoming call route.
      *
      * @param {String} loopVersion The version from the push notification, set
      *                             by the router from the URL.
      */
     incoming: function(loopVersion) {
-      window.navigator.mozLoop.startAlerting();
+      navigator.mozLoop.startAlerting();
       this._conversation.set({loopVersion: loopVersion});
       this._conversation.once("accept", function() {
         this.navigate("call/accept", {trigger: true});
       }.bind(this));
       this._conversation.once("decline", function() {
         this.navigate("call/decline", {trigger: true});
       }.bind(this));
       this._conversation.once("declineAndBlock", function() {
@@ -195,40 +171,40 @@ loop.conversation = (function(OT, mozL10
         model: this._conversation
       }));
     },
 
     /**
      * Accepts an incoming call.
      */
     accept: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       this._conversation.initiate({
         client: new loop.Client(),
         outgoing: false
       });
     },
 
     /**
      * Declines an incoming call.
      */
     decline: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       // XXX For now, we just close the window
       window.close();
     },
 
     /**
      * Decline and block an incoming call
      * @note:
      * - loopToken is the callUrl identifier. It gets set in the panel
      *   after a callUrl is received
      */
     declineAndBlock: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       var token = navigator.mozLoop.getLoopCharPref('loopToken');
       var client = new loop.Client();
       client.deleteCallUrl(token, function(error) {
         // XXX The conversation window will be closed when this cb is triggered
         // figure out if there is a better way to report the error to the user
         console.log(error);
       });
       window.close();
@@ -249,39 +225,45 @@ loop.conversation = (function(OT, mozL10
       /*jshint newcap:false*/
       this.loadReactComponent(sharedViews.ConversationView({
         sdk: OT,
         model: this._conversation
       }));
     },
 
     /**
-     * XXX: load a view with a close button for now?
+     * Call has ended, display a feedback form.
      */
-    ended: function() {
-      this.loadView(new EndedCallView());
+    feedback: function() {
+      document.title = mozL10n.get("call_has_ended");
+
+      this.loadReactComponent(sharedViews.FeedbackView({
+        feedbackApiClient: new loop.FeedbackAPIClient({
+          baseUrl: navigator.mozLoop.getLoopCharPref("feedback.baseUrl"),
+          product: navigator.mozLoop.getLoopCharPref("feedback.product")
+        })
+      }));
     }
   });
 
   /**
    * Panel initialisation.
    */
   function init() {
     // Do the initial L10n setup, we do this before anything
     // else to ensure the L10n environment is setup correctly.
-    mozL10n.initialize(window.navigator.mozLoop);
+    mozL10n.initialize(navigator.mozLoop);
 
     document.title = mozL10n.get("incoming_call_title");
 
     router = new ConversationRouter({
       conversation: new loop.shared.models.ConversationModel({}, {sdk: OT}),
       notifier: new sharedViews.NotificationListView({el: "#messages"})
     });
     Backbone.history.start();
   }
 
   return {
     ConversationRouter: ConversationRouter,
-    EndedCallView: EndedCallView,
     IncomingCallView: IncomingCallView,
     init: init
   };
 })(window.OT, document.mozL10n);
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -112,80 +112,56 @@ loop.conversation = (function(OT, mozL10
           </div>
         </div>
       );
       /* jshint ignore:end */
     }
   });
 
   /**
-   * Call ended view.
-   * @type {loop.shared.views.BaseView}
-   */
-  var EndedCallView = sharedViews.BaseView.extend({
-    template: _.template([
-      '<p>',
-      '  <button class="btn btn-info" data-l10n-id="close_window"></button>',
-      '</p>'
-    ].join("")),
-
-    className: "call-ended",
-
-    events: {
-      "click button": "closeWindow"
-    },
-
-    closeWindow: function(event) {
-      event.preventDefault();
-      // XXX For now, we just close the window.
-      window.close();
-    }
-  });
-
-  /**
    * Conversation router.
    *
    * Required options:
    * - {loop.shared.models.ConversationModel} conversation Conversation model.
    * - {loop.shared.components.Notifier}      notifier     Notifier component.
    *
    * @type {loop.shared.router.BaseConversationRouter}
    */
   var ConversationRouter = loop.desktopRouter.DesktopConversationRouter.extend({
     routes: {
       "incoming/:version": "incoming",
       "call/accept": "accept",
       "call/decline": "decline",
       "call/ongoing": "conversation",
-      "call/ended": "ended",
-      "call/declineAndBlock": "declineAndBlock"
+      "call/declineAndBlock": "declineAndBlock",
+      "call/feedback": "feedback"
     },
 
     /**
      * @override {loop.shared.router.BaseConversationRouter.startCall}
      */
     startCall: function() {
       this.navigate("call/ongoing", {trigger: true});
     },
 
     /**
      * @override {loop.shared.router.BaseConversationRouter.endCall}
      */
     endCall: function() {
-      this.navigate("call/ended", {trigger: true});
+      this.navigate("call/feedback", {trigger: true});
     },
 
     /**
      * Incoming call route.
      *
      * @param {String} loopVersion The version from the push notification, set
      *                             by the router from the URL.
      */
     incoming: function(loopVersion) {
-      window.navigator.mozLoop.startAlerting();
+      navigator.mozLoop.startAlerting();
       this._conversation.set({loopVersion: loopVersion});
       this._conversation.once("accept", function() {
         this.navigate("call/accept", {trigger: true});
       }.bind(this));
       this._conversation.once("decline", function() {
         this.navigate("call/decline", {trigger: true});
       }.bind(this));
       this._conversation.once("declineAndBlock", function() {
@@ -195,40 +171,40 @@ loop.conversation = (function(OT, mozL10
         model: this._conversation
       }));
     },
 
     /**
      * Accepts an incoming call.
      */
     accept: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       this._conversation.initiate({
         client: new loop.Client(),
         outgoing: false
       });
     },
 
     /**
      * Declines an incoming call.
      */
     decline: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       // XXX For now, we just close the window
       window.close();
     },
 
     /**
      * Decline and block an incoming call
      * @note:
      * - loopToken is the callUrl identifier. It gets set in the panel
      *   after a callUrl is received
      */
     declineAndBlock: function() {
-      window.navigator.mozLoop.stopAlerting();
+      navigator.mozLoop.stopAlerting();
       var token = navigator.mozLoop.getLoopCharPref('loopToken');
       var client = new loop.Client();
       client.deleteCallUrl(token, function(error) {
         // XXX The conversation window will be closed when this cb is triggered
         // figure out if there is a better way to report the error to the user
         console.log(error);
       });
       window.close();
@@ -249,39 +225,45 @@ loop.conversation = (function(OT, mozL10
       /*jshint newcap:false*/
       this.loadReactComponent(sharedViews.ConversationView({
         sdk: OT,
         model: this._conversation
       }));
     },
 
     /**
-     * XXX: load a view with a close button for now?
+     * Call has ended, display a feedback form.
      */
-    ended: function() {
-      this.loadView(new EndedCallView());
+    feedback: function() {
+      document.title = mozL10n.get("call_has_ended");
+
+      this.loadReactComponent(sharedViews.FeedbackView({
+        feedbackApiClient: new loop.FeedbackAPIClient({
+          baseUrl: navigator.mozLoop.getLoopCharPref("feedback.baseUrl"),
+          product: navigator.mozLoop.getLoopCharPref("feedback.product")
+        })
+      }));
     }
   });
 
   /**
    * Panel initialisation.
    */
   function init() {
     // Do the initial L10n setup, we do this before anything
     // else to ensure the L10n environment is setup correctly.
-    mozL10n.initialize(window.navigator.mozLoop);
+    mozL10n.initialize(navigator.mozLoop);
 
     document.title = mozL10n.get("incoming_call_title");
 
     router = new ConversationRouter({
       conversation: new loop.shared.models.ConversationModel({}, {sdk: OT}),
       notifier: new sharedViews.NotificationListView({el: "#messages"})
     });
     Backbone.history.start();
   }
 
   return {
     ConversationRouter: ConversationRouter,
-    EndedCallView: EndedCallView,
     IncomingCallView: IncomingCallView,
     init: init
   };
 })(window.OT, document.mozL10n);
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -103,22 +103,31 @@ loop.panel = (function(_, mozL10n) {
   });
 
   var ToSView = React.createClass({displayName: 'ToSView',
     getInitialState: function() {
       return {seenToS: navigator.mozLoop.getLoopCharPref('seenToS')};
     },
 
     render: function() {
-      var tosHTML = __("legal_text_and_links", {
-        "terms_of_use_url": "https://accounts.firefox.com/legal/terms",
-        "privacy_notice_url": "www.mozilla.org/privacy/"
-      });
-
       if (this.state.seenToS == "unseen") {
+        var terms_of_use_url = navigator.mozLoop.getLoopCharPref('legal.ToS_url');
+        var privacy_notice_url = navigator.mozLoop.getLoopCharPref('legal.privacy_url');
+        var tosHTML = __("legal_text_and_links2", {
+          "terms_of_use": React.renderComponentToStaticMarkup(
+            React.DOM.a({href: terms_of_use_url, target: "_blank"}, 
+              __("legal_text_tos")
+            )
+          ),
+          "privacy_notice": React.renderComponentToStaticMarkup(
+            React.DOM.a({href: privacy_notice_url, target: "_blank"}, 
+              __("legal_text_privacy")
+            )
+          ),
+        });
         navigator.mozLoop.setLoopCharPref('seenToS', 'seen');
         return React.DOM.p({className: "terms-service", 
                   dangerouslySetInnerHTML: {__html: tosHTML}});
       } else {
         return React.DOM.div(null);
       }
     }
   });
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -103,22 +103,31 @@ loop.panel = (function(_, mozL10n) {
   });
 
   var ToSView = React.createClass({
     getInitialState: function() {
       return {seenToS: navigator.mozLoop.getLoopCharPref('seenToS')};
     },
 
     render: function() {
-      var tosHTML = __("legal_text_and_links", {
-        "terms_of_use_url": "https://accounts.firefox.com/legal/terms",
-        "privacy_notice_url": "www.mozilla.org/privacy/"
-      });
-
       if (this.state.seenToS == "unseen") {
+        var terms_of_use_url = navigator.mozLoop.getLoopCharPref('legal.ToS_url');
+        var privacy_notice_url = navigator.mozLoop.getLoopCharPref('legal.privacy_url');
+        var tosHTML = __("legal_text_and_links2", {
+          "terms_of_use": React.renderComponentToStaticMarkup(
+            <a href={terms_of_use_url} target="_blank">
+              {__("legal_text_tos")}
+            </a>
+          ),
+          "privacy_notice": React.renderComponentToStaticMarkup(
+            <a href={privacy_notice_url} target="_blank">
+              {__("legal_text_privacy")}
+            </a>
+          ),
+        });
         navigator.mozLoop.setLoopCharPref('seenToS', 'seen');
         return <p className="terms-service"
                   dangerouslySetInnerHTML={{__html: tosHTML}}></p>;
       } else {
         return <div />;
       }
     }
   });
--- a/browser/components/loop/content/panel.html
+++ b/browser/components/loop/content/panel.html
@@ -10,17 +10,17 @@
     <link rel="stylesheet" type="text/css" href="loop/shared/css/panel.css">
   </head>
   <body class="panel" onload="loop.panel.init();">
 
     <div id="messages"></div>
 
     <div id="main"></div>
 
-    <script type="text/javascript" src="loop/shared/libs/react-0.10.0.js"></script>
+    <script type="text/javascript" src="loop/shared/libs/react-0.11.1.js"></script>
     <script type="text/javascript" src="loop/libs/l10n.js"></script>
     <script type="text/javascript" src="loop/shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="loop/shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="loop/shared/libs/backbone-1.1.2.js"></script>
 
     <script type="text/javascript" src="loop/shared/js/models.js"></script>
     <script type="text/javascript" src="loop/shared/js/router.js"></script>
     <script type="text/javascript" src="loop/shared/js/views.js"></script>
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -233,8 +233,110 @@
   color: #000;
   cursor: pointer;
 }
 
   .decline-block-menu li:hover {
     color: #FFF;
     background: #111;
   }
+
+/* Expired call url page */
+
+.expired-url-info {
+  width: 400px;
+  margin: 0 auto;
+}
+
+.promote-firefox {
+  text-align: center;
+  font-size: 18px;
+  line-height: 24px;
+  margin: 2em 0;
+}
+
+.promote-firefox h3 {
+  font-weight: 300;
+}
+
+/* Feedback form */
+
+.feedback {
+  padding: 1em;
+}
+
+.feedback h3 {
+  color: #666;
+  font-size: 12px;
+  font-weight: 700;
+  text-align: center;
+  margin-bottom: 10px;
+  margin-top: 15px;
+}
+
+.feedback .faces {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  padding: 20px 0;
+}
+
+.feedback .face {
+  border: 1px solid transparent;
+  box-shadow: 0px 1px 2px #CCC;
+  cursor: pointer;
+  border-radius: 4px;
+  margin: 0px 10px;
+  width: 80px;
+  height: 80px;
+  background-color: #fbfbfb;
+  background-size: 60px auto;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.feedback .face:hover {
+  border: 1px solid #DDD;
+  background-color: #FEFEFE;
+}
+
+.feedback .face.face-happy {
+  background-image: url("../img/happy.png");
+}
+
+.feedback .face.face-sad {
+  background-image: url("../img/sad.png");
+}
+
+.feedback button.back {
+  border-radius: 2px;
+  border: 1px solid #CCC;
+  color: #CCC;
+  font-size: 11px;
+  cursor: pointer;
+  padding: 3px 10px;
+  display: inline;
+  margin-bottom: 1em;
+}
+
+.feedback label {
+  display: block;
+}
+
+.feedback form input[type="radio"] {
+  margin-right: .5em;
+}
+
+.feedback form button[type="submit"] {
+  width: 100%;
+}
+
+.feedback form input[type="text"] {
+  width: 100%;
+}
+
+.feedback .info {
+  display: block;
+  font-size: 10px;
+  color: #CCC;
+  text-align: center;
+}
new file mode 100644
index 0000000000000000000000000000000000000000..8e79faf9c6c9408bb6d990659118f1166c721822
GIT binary patch
literal 40247
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
new file mode 100644
index 0000000000000000000000000000000000000000..13f2dbb88f4df2fb36c943979dac82341cce7678
GIT binary patch
literal 40649
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
KZty3;G2(xKq55F}
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/js/feedbackApiClient.js
@@ -0,0 +1,92 @@
+/* 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/. */
+
+/* global loop:true */
+
+var loop = loop || {};
+loop.FeedbackAPIClient = (function($) {
+  "use strict";
+
+  /**
+   * Feedback API client. Sends feedback data to an input.mozilla.com compatible
+   * API.
+   *
+   * Available settings:
+   * - {String} baseUrl Base API url (required)
+   * - {String} product Product name (required)
+   *
+   * @param {Object} settings Settings.
+   * @link  http://fjord.readthedocs.org/en/latest/api.html
+   */
+  function FeedbackAPIClient(settings) {
+    settings = settings || {};
+    if (!settings.hasOwnProperty("baseUrl")) {
+      throw new Error("Missing required baseUrl setting.");
+    }
+    this._baseUrl = settings.baseUrl;
+    if (!settings.hasOwnProperty("product")) {
+      throw new Error("Missing required product setting.");
+    }
+    this._product = settings.product;
+  }
+
+  FeedbackAPIClient.prototype = {
+    /**
+     * Formats Feedback data to match the API spec.
+     *
+     * @param  {Object} fields Feedback form data.
+     * @return {Object}        Formatted data.
+     */
+    _formatData: function(fields) {
+      var formatted = {};
+
+      if (typeof fields !== "object") {
+        throw new Error("Invalid feedback data provided.");
+      }
+
+      formatted.product = this._product;
+      formatted.happy = fields.happy;
+      formatted.category = fields.category;
+
+      // Default description field value
+      if (!fields.description) {
+        formatted.description = (fields.happy ? "Happy" : "Sad") + " User";
+      } else {
+        formatted.description = fields.description;
+      }
+
+      return formatted;
+    },
+
+    /**
+     * Sends feedback data.
+     *
+     * @param  {Object}   fields Feedback form data.
+     * @param  {Function} cb     Callback(err, result)
+     */
+    send: function(fields, cb) {
+      var req = $.ajax({
+        url:         this._baseUrl,
+        method:      "POST",
+        contentType: "application/json",
+        dataType:    "json",
+        data: JSON.stringify(this._formatData(fields))
+      });
+
+      req.done(function(result) {
+        console.info("User feedback data have been submitted", result);
+        cb(null, result);
+      });
+
+      req.fail(function(jqXHR, textStatus, errorThrown) {
+        var message = "Error posting user feedback data";
+        var httpError = jqXHR.status + " " + errorThrown;
+        console.error(message, httpError, JSON.stringify(jqXHR.responseJSON));
+        cb(new Error(message + ": " + httpError));
+      });
+    }
+  };
+
+  return FeedbackAPIClient;
+})(jQuery);
--- a/browser/components/loop/content/shared/js/router.js
+++ b/browser/components/loop/content/shared/js/router.js
@@ -161,17 +161,16 @@ loop.shared.router = (function(l10n) {
     _onSessionReady: function() {
       this.startCall();
     },
 
     /**
      * Session has ended. Notifies the user and ends the call.
      */
     _onSessionEnded: function() {
-      this._notifier.warnL10n("call_has_ended");
       this.endCall();
     },
 
     /**
      * Peer hung up. Notifies the user and ends the call.
      *
      * Event properties:
      * - {String} connectionId: OT session id
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -8,16 +8,17 @@
 /* global loop:true, React */
 var loop = loop || {};
 loop.shared = loop.shared || {};
 loop.shared.views = (function(_, OT, l10n) {
   "use strict";
 
   var sharedModels = loop.shared.models;
   var __ = l10n.get;
+  var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5;
 
   /**
    * L10n view. Translates resulting view DOM fragment once rendered.
    */
   var L10nView = (function() {
     var L10nViewImpl   = Backbone.View.extend(), // Original View constructor
         originalExtend = L10nViewImpl.extend;    // Original static extend fn
 
@@ -348,16 +349,249 @@ loop.shared.views = (function(_, OT, l10
           )
         )
       );
       /* jshint ignore:end */
     }
   });
 
   /**
+   * Feedback outer layout.
+   *
+   * Props:
+   * -
+   */
+  var FeedbackLayout = React.createClass({displayName: 'FeedbackLayout',
+    propTypes: {
+      children: React.PropTypes.component.isRequired,
+      title: React.PropTypes.string.isRequired,
+      reset: React.PropTypes.func // if not specified, no Back btn is shown
+    },
+
+    render: function() {
+      var backButton = React.DOM.div(null);
+      if (this.props.reset) {
+        backButton = (
+          React.DOM.button({className: "back", type: "button", onClick: this.props.reset}, 
+            "« ", __("feedback_back_button")
+          )
+        );
+      }
+      return (
+        React.DOM.div({className: "feedback"}, 
+          backButton, 
+          React.DOM.h3(null, this.props.title), 
+          this.props.children
+        )
+      );
+    }
+  });
+
+  /**
+   * Detailed feedback form.
+   */
+  var FeedbackForm = React.createClass({displayName: 'FeedbackForm',
+    propTypes: {
+      pending:      React.PropTypes.bool,
+      sendFeedback: React.PropTypes.func,
+      reset:        React.PropTypes.func
+    },
+
+    getInitialState: function() {
+      return {category: "", description: ""};
+    },
+
+    getInitialProps: function() {
+      return {pending: false};
+    },
+
+    _getCategories: function() {
+      return {
+        audio_quality: __("feedback_category_audio_quality"),
+        video_quality: __("feedback_category_video_quality"),
+        disconnected : __("feedback_category_was_disconnected"),
+        confusing:     __("feedback_category_confusing"),
+        other:         __("feedback_category_other")
+      };
+    },
+
+    _getCategoryFields: function() {
+      var categories = this._getCategories();
+      return Object.keys(categories).map(function(category, key) {
+        return (
+          React.DOM.label({key: key}, 
+            React.DOM.input({type: "radio", ref: "category", name: "category", 
+                   value: category, 
+                   onChange: this.handleCategoryChange}), 
+            categories[category]
+          )
+        );
+      }, this);
+    },
+
+    /**
+     * Checks if the form is ready for submission:
+     * - a category (reason) must be chosen
+     * - no feedback submission should be pending
+     *
+     * @return {Boolean}
+     */
+    _isFormReady: function() {
+      return this.state.category !== "" && !this.props.pending;
+    },
+
+    handleCategoryChange: function(event) {
+      var category = event.target.value;
+      if (category !== "other") {
+        // resets description text field
+        this.setState({description: ""});
+      }
+      this.setState({category: category});
+    },
+
+    handleCustomTextChange: function(event) {
+      this.setState({description: event.target.value});
+    },
+
+    handleFormSubmit: function(event) {
+      event.preventDefault();
+      this.props.sendFeedback({
+        happy: false,
+        category: this.state.category,
+        description: this.state.description
+      });
+    },
+
+    render: function() {
+      return (
+        FeedbackLayout({title: __("feedback_what_makes_you_sad"), 
+                        reset: this.props.reset}, 
+          React.DOM.form({onSubmit: this.handleFormSubmit}, 
+            this._getCategoryFields(), 
+            React.DOM.p(null, React.DOM.input({type: "text", ref: "description", name: "description", 
+                      disabled: this.state.category !== "other", 
+                      onChange: this.handleCustomTextChange, 
+                      value: this.state.description})), 
+            React.DOM.button({type: "submit", className: "btn btn-success", 
+                    disabled: !this._isFormReady()}, 
+              __("feedback_submit_button")
+            )
+          )
+        )
+      );
+    }
+  });
+
+  /**
+   * Feedback received view.
+   */
+  var FeedbackReceived = React.createClass({displayName: 'FeedbackReceived',
+    getInitialState: function() {
+      return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS};
+    },
+
+    componentDidMount: function() {
+      this._timer = setInterval(function() {
+        this.setState({countdown: this.state.countdown - 1});
+      }.bind(this), 1000);
+    },
+
+    componentWillUnmount: function() {
+      if (this._timer) {
+        clearInterval(this._timer);
+      }
+    },
+
+    render: function() {
+      if (this.state.countdown < 1) {
+        clearInterval(this._timer);
+        window.close();
+      }
+      return (
+        FeedbackLayout({title: __("feedback_thank_you_heading")}, 
+          React.DOM.p({className: "info thank-you"}, __("feedback_window_will_close_in", {
+            countdown: this.state.countdown
+          }))
+        )
+      );
+    }
+  });
+
+  /**
+   * Feedback view.
+   */
+  var FeedbackView = React.createClass({displayName: 'FeedbackView',
+    propTypes: {
+      // A loop.FeedbackAPIClient instance
+      feedbackApiClient: React.PropTypes.object.isRequired,
+      // The current feedback submission flow step name
+      step: React.PropTypes.oneOf(["start", "form", "finished"])
+    },
+
+    getInitialState: function() {
+      return {pending: false, step: this.props.step || "start"};
+    },
+
+    getInitialProps: function() {
+      return {step: "start"};
+    },
+
+    reset: function() {
+      this.setState(this.getInitialState());
+    },
+
+    handleHappyClick: function() {
+      this.sendFeedback({happy: true}, this._onFeedbackSent);
+    },
+
+    handleSadClick: function() {
+      this.setState({step: "form"});
+    },
+
+    sendFeedback: function(fields) {
+      // Setting state.pending to true will disable the submit button to avoid
+      // multiple submissions
+      this.setState({pending: true});
+      // Sends feedback data
+      this.props.feedbackApiClient.send(fields, this._onFeedbackSent);
+    },
+
+    _onFeedbackSent: function(err) {
+      if (err) {
+        // XXX better end user error reporting, see bug 1046738
+        console.error("Unable to send user feedback", err);
+      }
+      this.setState({pending: false, step: "finished"});
+    },
+
+    render: function() {
+      switch(this.state.step) {
+        case "finished":
+          return FeedbackReceived(null);
+        case "form":
+          return FeedbackForm({feedbackApiClient: this.props.feedbackApiClient, 
+                               sendFeedback: this.sendFeedback, 
+                               reset: this.reset, 
+                               pending: this.state.pending});
+        default:
+          return (
+            FeedbackLayout({title: __("feedback_call_experience_heading")}, 
+              React.DOM.div({className: "faces"}, 
+                React.DOM.button({className: "face face-happy", 
+                        onClick: this.handleHappyClick}), 
+                React.DOM.button({className: "face face-sad", 
+                        onClick: this.handleSadClick})
+              )
+            )
+          );
+      }
+    }
+  });
+
+  /**
    * Notification view.
    */
   var NotificationView = BaseView.extend({
     template: _.template([
       '<div class="alert alert-<%- level %>">',
       '  <button class="close"></button>',
       '  <p class="message"><%- message %></p>',
       '</div>'
@@ -513,15 +747,16 @@ loop.shared.views = (function(_, OT, l10
     ].join(""))
   });
 
   return {
     L10nView: L10nView,
     BaseView: BaseView,
     ConversationView: ConversationView,
     ConversationToolbar: ConversationToolbar,
+    FeedbackView: FeedbackView,
     MediaControlButton: MediaControlButton,
     NotificationListView: NotificationListView,
     NotificationView: NotificationView,
     UnsupportedBrowserView: UnsupportedBrowserView,
     UnsupportedDeviceView: UnsupportedDeviceView
   };
 })(_, window.OT, document.webL10n || document.mozL10n);
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -8,16 +8,17 @@
 /* global loop:true, React */
 var loop = loop || {};
 loop.shared = loop.shared || {};
 loop.shared.views = (function(_, OT, l10n) {
   "use strict";
 
   var sharedModels = loop.shared.models;
   var __ = l10n.get;
+  var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5;
 
   /**
    * L10n view. Translates resulting view DOM fragment once rendered.
    */
   var L10nView = (function() {
     var L10nViewImpl   = Backbone.View.extend(), // Original View constructor
         originalExtend = L10nViewImpl.extend;    // Original static extend fn
 
@@ -348,16 +349,249 @@ loop.shared.views = (function(_, OT, l10
           </div>
         </div>
       );
       /* jshint ignore:end */
     }
   });
 
   /**
+   * Feedback outer layout.
+   *
+   * Props:
+   * -
+   */
+  var FeedbackLayout = React.createClass({
+    propTypes: {
+      children: React.PropTypes.component.isRequired,
+      title: React.PropTypes.string.isRequired,
+      reset: React.PropTypes.func // if not specified, no Back btn is shown
+    },
+
+    render: function() {
+      var backButton = <div />;
+      if (this.props.reset) {
+        backButton = (
+          <button className="back" type="button" onClick={this.props.reset}>
+            &laquo;&nbsp;{__("feedback_back_button")}
+          </button>
+        );
+      }
+      return (
+        <div className="feedback">
+          {backButton}
+          <h3>{this.props.title}</h3>
+          {this.props.children}
+        </div>
+      );
+    }
+  });
+
+  /**
+   * Detailed feedback form.
+   */
+  var FeedbackForm = React.createClass({
+    propTypes: {
+      pending:      React.PropTypes.bool,
+      sendFeedback: React.PropTypes.func,
+      reset:        React.PropTypes.func
+    },
+
+    getInitialState: function() {
+      return {category: "", description: ""};
+    },
+
+    getInitialProps: function() {
+      return {pending: false};
+    },
+
+    _getCategories: function() {
+      return {
+        audio_quality: __("feedback_category_audio_quality"),
+        video_quality: __("feedback_category_video_quality"),
+        disconnected : __("feedback_category_was_disconnected"),
+        confusing:     __("feedback_category_confusing"),
+        other:         __("feedback_category_other")
+      };
+    },
+
+    _getCategoryFields: function() {
+      var categories = this._getCategories();
+      return Object.keys(categories).map(function(category, key) {
+        return (
+          <label key={key}>
+            <input type="radio" ref="category" name="category"
+                   value={category}
+                   onChange={this.handleCategoryChange} />
+            {categories[category]}
+          </label>
+        );
+      }, this);
+    },
+
+    /**
+     * Checks if the form is ready for submission:
+     * - a category (reason) must be chosen
+     * - no feedback submission should be pending
+     *
+     * @return {Boolean}
+     */
+    _isFormReady: function() {
+      return this.state.category !== "" && !this.props.pending;
+    },
+
+    handleCategoryChange: function(event) {
+      var category = event.target.value;
+      if (category !== "other") {
+        // resets description text field
+        this.setState({description: ""});
+      }
+      this.setState({category: category});
+    },
+
+    handleCustomTextChange: function(event) {
+      this.setState({description: event.target.value});
+    },
+
+    handleFormSubmit: function(event) {
+      event.preventDefault();
+      this.props.sendFeedback({
+        happy: false,
+        category: this.state.category,
+        description: this.state.description
+      });
+    },
+
+    render: function() {
+      return (
+        <FeedbackLayout title={__("feedback_what_makes_you_sad")}
+                        reset={this.props.reset}>
+          <form onSubmit={this.handleFormSubmit}>
+            {this._getCategoryFields()}
+            <p><input type="text" ref="description" name="description"
+                      disabled={this.state.category !== "other"}
+                      onChange={this.handleCustomTextChange}
+                      value={this.state.description} /></p>
+            <button type="submit" className="btn btn-success"
+                    disabled={!this._isFormReady()}>
+              {__("feedback_submit_button")}
+            </button>
+          </form>
+        </FeedbackLayout>
+      );
+    }
+  });
+
+  /**
+   * Feedback received view.
+   */
+  var FeedbackReceived = React.createClass({
+    getInitialState: function() {
+      return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS};
+    },
+
+    componentDidMount: function() {
+      this._timer = setInterval(function() {
+        this.setState({countdown: this.state.countdown - 1});
+      }.bind(this), 1000);
+    },
+
+    componentWillUnmount: function() {
+      if (this._timer) {
+        clearInterval(this._timer);
+      }
+    },
+
+    render: function() {
+      if (this.state.countdown < 1) {
+        clearInterval(this._timer);
+        window.close();
+      }
+      return (
+        <FeedbackLayout title={__("feedback_thank_you_heading")}>
+          <p className="info thank-you">{__("feedback_window_will_close_in", {
+            countdown: this.state.countdown
+          })}</p>
+        </FeedbackLayout>
+      );
+    }
+  });
+
+  /**
+   * Feedback view.
+   */
+  var FeedbackView = React.createClass({
+    propTypes: {
+      // A loop.FeedbackAPIClient instance
+      feedbackApiClient: React.PropTypes.object.isRequired,
+      // The current feedback submission flow step name
+      step: React.PropTypes.oneOf(["start", "form", "finished"])
+    },
+
+    getInitialState: function() {
+      return {pending: false, step: this.props.step || "start"};
+    },
+
+    getInitialProps: function() {
+      return {step: "start"};
+    },
+
+    reset: function() {
+      this.setState(this.getInitialState());
+    },
+
+    handleHappyClick: function() {
+      this.sendFeedback({happy: true}, this._onFeedbackSent);
+    },
+
+    handleSadClick: function() {
+      this.setState({step: "form"});
+    },
+
+    sendFeedback: function(fields) {
+      // Setting state.pending to true will disable the submit button to avoid
+      // multiple submissions
+      this.setState({pending: true});
+      // Sends feedback data
+      this.props.feedbackApiClient.send(fields, this._onFeedbackSent);
+    },
+
+    _onFeedbackSent: function(err) {
+      if (err) {
+        // XXX better end user error reporting, see bug 1046738
+        console.error("Unable to send user feedback", err);
+      }
+      this.setState({pending: false, step: "finished"});
+    },
+
+    render: function() {
+      switch(this.state.step) {
+        case "finished":
+          return <FeedbackReceived />;
+        case "form":
+          return <FeedbackForm feedbackApiClient={this.props.feedbackApiClient}
+                               sendFeedback={this.sendFeedback}
+                               reset={this.reset}
+                               pending={this.state.pending} />;
+        default:
+          return (
+            <FeedbackLayout title={__("feedback_call_experience_heading")}>
+              <div className="faces">
+                <button className="face face-happy"
+                        onClick={this.handleHappyClick}></button>
+                <button className="face face-sad"
+                        onClick={this.handleSadClick}></button>
+              </div>
+            </FeedbackLayout>
+          );
+      }
+    }
+  });
+
+  /**
    * Notification view.
    */
   var NotificationView = BaseView.extend({
     template: _.template([
       '<div class="alert alert-<%- level %>">',
       '  <button class="close"></button>',
       '  <p class="message"><%- message %></p>',
       '</div>'
@@ -513,15 +747,16 @@ loop.shared.views = (function(_, OT, l10
     ].join(""))
   });
 
   return {
     L10nView: L10nView,
     BaseView: BaseView,
     ConversationView: ConversationView,
     ConversationToolbar: ConversationToolbar,
+    FeedbackView: FeedbackView,
     MediaControlButton: MediaControlButton,
     NotificationListView: NotificationListView,
     NotificationView: NotificationView,
     UnsupportedBrowserView: UnsupportedBrowserView,
     UnsupportedDeviceView: UnsupportedDeviceView
   };
 })(_, window.OT, document.webL10n || document.mozL10n);
rename from browser/components/loop/content/shared/libs/react-0.10.0.js
rename to browser/components/loop/content/shared/libs/react-0.11.1.js
--- a/browser/components/loop/content/shared/libs/react-0.10.0.js
+++ b/browser/components/loop/content/shared/libs/react-0.11.1.js
@@ -1,12 +1,12 @@
 /**
- * React (with addons) v0.10.0
- */
-!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+ * React (with addons) v0.11.1
+ */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -30,17 +30,241 @@ var AutoFocusMixin = {
     if (this.props.autoFocus) {
       focusNode(this.getDOMNode());
     }
   }
 };
 
 module.exports = AutoFocusMixin;
 
-},{"./focusNode":113}],2:[function(_dereq_,module,exports){
+},{"./focusNode":120}],2:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule BeforeInputEventPlugin
+ * @typechecks static-only
+ */
+
+"use strict";
+
+var EventConstants = _dereq_("./EventConstants");
+var EventPropagators = _dereq_("./EventPropagators");
+var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
+var SyntheticInputEvent = _dereq_("./SyntheticInputEvent");
+
+var keyOf = _dereq_("./keyOf");
+
+var canUseTextInputEvent = (
+  ExecutionEnvironment.canUseDOM &&
+  'TextEvent' in window &&
+  !('documentMode' in document || isPresto())
+);
+
+/**
+ * Opera <= 12 includes TextEvent in window, but does not fire
+ * text input events. Rely on keypress instead.
+ */
+function isPresto() {
+  var opera = window.opera;
+  return (
+    typeof opera === 'object' &&
+    typeof opera.version === 'function' &&
+    parseInt(opera.version(), 10) <= 12
+  );
+}
+
+var SPACEBAR_CODE = 32;
+var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
+
+var topLevelTypes = EventConstants.topLevelTypes;
+
+// Events and their corresponding property names.
+var eventTypes = {
+  beforeInput: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onBeforeInput: null}),
+      captured: keyOf({onBeforeInputCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topCompositionEnd,
+      topLevelTypes.topKeyPress,
+      topLevelTypes.topTextInput,
+      topLevelTypes.topPaste
+    ]
+  }
+};
+
+// Track characters inserted via keypress and composition events.
+var fallbackChars = null;
+
+/**
+ * Return whether a native keypress event is assumed to be a command.
+ * This is required because Firefox fires `keypress` events for key commands
+ * (cut, copy, select-all, etc.) even though no character is inserted.
+ */
+function isKeypressCommand(nativeEvent) {
+  return (
+    (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
+    // ctrlKey && altKey is equivalent to AltGr, and is not a command.
+    !(nativeEvent.ctrlKey && nativeEvent.altKey)
+  );
+}
+
+/**
+ * Create an `onBeforeInput` event to match
+ * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
+ *
+ * This event plugin is based on the native `textInput` event
+ * available in Chrome, Safari, Opera, and IE. This event fires after
+ * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ *
+ * `beforeInput` is spec'd but not implemented in any browsers, and
+ * the `input` event does not provide any useful information about what has
+ * actually been added, contrary to the spec. Thus, `textInput` is the best
+ * available event to identify the characters that have actually been inserted
+ * into the target node.
+ */
+var BeforeInputEventPlugin = {
+
+  eventTypes: eventTypes,
+
+  /**
+   * @param {string} topLevelType Record from `EventConstants`.
+   * @param {DOMEventTarget} topLevelTarget The listening component root node.
+   * @param {string} topLevelTargetID ID of `topLevelTarget`.
+   * @param {object} nativeEvent Native browser event.
+   * @return {*} An accumulation of synthetic events.
+   * @see {EventPluginHub.extractEvents}
+   */
+  extractEvents: function(
+      topLevelType,
+      topLevelTarget,
+      topLevelTargetID,
+      nativeEvent) {
+
+    var chars;
+
+    if (canUseTextInputEvent) {
+      switch (topLevelType) {
+        case topLevelTypes.topKeyPress:
+          /**
+           * If native `textInput` events are available, our goal is to make
+           * use of them. However, there is a special case: the spacebar key.
+           * In Webkit, preventing default on a spacebar `textInput` event
+           * cancels character insertion, but it *also* causes the browser
+           * to fall back to its default spacebar behavior of scrolling the
+           * page.
+           *
+           * Tracking at:
+           * https://code.google.com/p/chromium/issues/detail?id=355103
+           *
+           * To avoid this issue, use the keypress event as if no `textInput`
+           * event is available.
+           */
+          var which = nativeEvent.which;
+          if (which !== SPACEBAR_CODE) {
+            return;
+          }
+
+          chars = String.fromCharCode(which);
+          break;
+
+        case topLevelTypes.topTextInput:
+          // Record the characters to be added to the DOM.
+          chars = nativeEvent.data;
+
+          // If it's a spacebar character, assume that we have already handled
+          // it at the keypress level and bail immediately.
+          if (chars === SPACEBAR_CHAR) {
+            return;
+          }
+
+          // Otherwise, carry on.
+          break;
+
+        default:
+          // For other native event types, do nothing.
+          return;
+      }
+    } else {
+      switch (topLevelType) {
+        case topLevelTypes.topPaste:
+          // If a paste event occurs after a keypress, throw out the input
+          // chars. Paste events should not lead to BeforeInput events.
+          fallbackChars = null;
+          break;
+        case topLevelTypes.topKeyPress:
+          /**
+           * As of v27, Firefox may fire keypress events even when no character
+           * will be inserted. A few possibilities:
+           *
+           * - `which` is `0`. Arrow keys, Esc key, etc.
+           *
+           * - `which` is the pressed key code, but no char is available.
+           *   Ex: 'AltGr + d` in Polish. There is no modified character for
+           *   this key combination and no character is inserted into the
+           *   document, but FF fires the keypress for char code `100` anyway.
+           *   No `input` event will occur.
+           *
+           * - `which` is the pressed key code, but a command combination is
+           *   being used. Ex: `Cmd+C`. No character is inserted, and no
+           *   `input` event will occur.
+           */
+          if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
+            fallbackChars = String.fromCharCode(nativeEvent.which);
+          }
+          break;
+        case topLevelTypes.topCompositionEnd:
+          fallbackChars = nativeEvent.data;
+          break;
+      }
+
+      // If no changes have occurred to the fallback string, no relevant
+      // event has fired and we're done.
+      if (fallbackChars === null) {
+        return;
+      }
+
+      chars = fallbackChars;
+    }
+
+    // If no characters are being inserted, no BeforeInput event should
+    // be fired.
+    if (!chars) {
+      return;
+    }
+
+    var event = SyntheticInputEvent.getPooled(
+      eventTypes.beforeInput,
+      topLevelTargetID,
+      nativeEvent
+    );
+
+    event.data = chars;
+    fallbackChars = null;
+    EventPropagators.accumulateTwoPhaseDispatches(event);
+    return event;
+  }
+};
+
+module.exports = BeforeInputEventPlugin;
+
+},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./SyntheticInputEvent":98,"./keyOf":141}],3:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -147,17 +371,17 @@ var CSSCore = {
     }
     return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1;
   }
 
 };
 
 module.exports = CSSCore;
 
-},{"./invariant":125}],3:[function(_dereq_,module,exports){
+},{"./invariant":134}],4:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -270,17 +494,17 @@ var shorthandPropertyExpansions = {
 
 var CSSProperty = {
   isUnitlessNumber: isUnitlessNumber,
   shorthandPropertyExpansions: shorthandPropertyExpansions
 };
 
 module.exports = CSSProperty;
 
-},{}],4:[function(_dereq_,module,exports){
+},{}],5:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -295,36 +519,36 @@ module.exports = CSSProperty;
  * @typechecks static-only
  */
 
 "use strict";
 
 var CSSProperty = _dereq_("./CSSProperty");
 
 var dangerousStyleValue = _dereq_("./dangerousStyleValue");
-var escapeTextForBrowser = _dereq_("./escapeTextForBrowser");
-var hyphenate = _dereq_("./hyphenate");
+var hyphenateStyleName = _dereq_("./hyphenateStyleName");
 var memoizeStringOnly = _dereq_("./memoizeStringOnly");
 
 var processStyleName = memoizeStringOnly(function(styleName) {
-  return escapeTextForBrowser(hyphenate(styleName));
+  return hyphenateStyleName(styleName);
 });
 
 /**
  * Operations for dealing with CSS properties.
  */
 var CSSPropertyOperations = {
 
   /**
    * Serializes a mapping of style properties for use as inline styles:
    *
    *   > createMarkupForStyles({width: '200px', height: 0})
    *   "width:200px;height:0;"
    *
    * Undefined values are ignored so that declarative programming is easier.
+   * The result should be HTML-escaped before insertion into the DOM.
    *
    * @param {object} styles
    * @return {?string}
    */
   createMarkupForStyles: function(styles) {
     var serialized = '';
     for (var styleName in styles) {
       if (!styles.hasOwnProperty(styleName)) {
@@ -369,17 +593,122 @@ var CSSPropertyOperations = {
       }
     }
   }
 
 };
 
 module.exports = CSSPropertyOperations;
 
-},{"./CSSProperty":3,"./dangerousStyleValue":108,"./escapeTextForBrowser":111,"./hyphenate":123,"./memoizeStringOnly":133}],5:[function(_dereq_,module,exports){
+},{"./CSSProperty":4,"./dangerousStyleValue":115,"./hyphenateStyleName":132,"./memoizeStringOnly":143}],6:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule CallbackQueue
+ */
+
+"use strict";
+
+var PooledClass = _dereq_("./PooledClass");
+
+var invariant = _dereq_("./invariant");
+var mixInto = _dereq_("./mixInto");
+
+/**
+ * A specialized pseudo-event module to help keep track of components waiting to
+ * be notified when their DOM representations are available for use.
+ *
+ * This implements `PooledClass`, so you should never need to instantiate this.
+ * Instead, use `CallbackQueue.getPooled()`.
+ *
+ * @class ReactMountReady
+ * @implements PooledClass
+ * @internal
+ */
+function CallbackQueue() {
+  this._callbacks = null;
+  this._contexts = null;
+}
+
+mixInto(CallbackQueue, {
+
+  /**
+   * Enqueues a callback to be invoked when `notifyAll` is invoked.
+   *
+   * @param {function} callback Invoked when `notifyAll` is invoked.
+   * @param {?object} context Context to call `callback` with.
+   * @internal
+   */
+  enqueue: function(callback, context) {
+    this._callbacks = this._callbacks || [];
+    this._contexts = this._contexts || [];
+    this._callbacks.push(callback);
+    this._contexts.push(context);
+  },
+
+  /**
+   * Invokes all enqueued callbacks and clears the queue. This is invoked after
+   * the DOM representation of a component has been created or updated.
+   *
+   * @internal
+   */
+  notifyAll: function() {
+    var callbacks = this._callbacks;
+    var contexts = this._contexts;
+    if (callbacks) {
+      ("production" !== "development" ? invariant(
+        callbacks.length === contexts.length,
+        "Mismatched list of contexts in callback queue"
+      ) : invariant(callbacks.length === contexts.length));
+      this._callbacks = null;
+      this._contexts = null;
+      for (var i = 0, l = callbacks.length; i < l; i++) {
+        callbacks[i].call(contexts[i]);
+      }
+      callbacks.length = 0;
+      contexts.length = 0;
+    }
+  },
+
+  /**
+   * Resets the internal queue.
+   *
+   * @internal
+   */
+  reset: function() {
+    this._callbacks = null;
+    this._contexts = null;
+  },
+
+  /**
+   * `PooledClass` looks for this.
+   */
+  destructor: function() {
+    this.reset();
+  }
+
+});
+
+PooledClass.addPoolingTo(CallbackQueue);
+
+module.exports = CallbackQueue;
+
+},{"./PooledClass":28,"./invariant":134,"./mixInto":147}],7:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -457,17 +786,17 @@ function manualDispatchChangeEvent(nativ
   var event = SyntheticEvent.getPooled(
     eventTypes.change,
     activeElementID,
     nativeEvent
   );
   EventPropagators.accumulateTwoPhaseDispatches(event);
 
   // If change and propertychange bubbled, we'd just bind to it like all the
-  // other events and have it go through ReactEventTopLevelCallback. Since it
+  // other events and have it go through ReactBrowserEventEmitter. Since it
   // doesn't, we manually listen for the events and so we have to enqueue and
   // process the abstract event manually.
   //
   // Batching is necessary here in order to ensure that all event handlers run
   // before the next rerender (including event handlers attached to ancestor
   // elements instead of directly on the input). Without this, controlled
   // components don't work properly in conjunction with event bubbling because
   // the component is rerendered and the value reverted before all the event
@@ -758,17 +1087,17 @@ var ChangeEventPlugin = {
       );
     }
   }
 
 };
 
 module.exports = ChangeEventPlugin;
 
-},{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactUpdates":81,"./SyntheticEvent":89,"./isEventSupported":126,"./isTextInputElement":128,"./keyOf":132}],6:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./EventPluginHub":18,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactUpdates":87,"./SyntheticEvent":96,"./isEventSupported":135,"./isTextInputElement":137,"./keyOf":141}],8:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -790,17 +1119,17 @@ var nextReactRootIndex = 0;
 var ClientReactRootIndex = {
   createReactRootIndex: function() {
     return nextReactRootIndex++;
   }
 };
 
 module.exports = ClientReactRootIndex;
 
-},{}],7:[function(_dereq_,module,exports){
+},{}],9:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -837,17 +1166,21 @@ var useCompositionEvent = (
 // In IE9+, we have access to composition events, but the data supplied
 // by the native compositionend event may be incorrect. In Korean, for example,
 // the compositionend event contains only one character regardless of
 // how many characters have been composed since compositionstart.
 // We therefore use the fallback data while still using the native
 // events as triggers.
 var useFallbackData = (
   !useCompositionEvent ||
-  'documentMode' in document && document.documentMode > 8
+  (
+    'documentMode' in document &&
+    document.documentMode > 8 &&
+    document.documentMode <= 11
+  )
 );
 
 var topLevelTypes = EventConstants.topLevelTypes;
 var currentComposition = null;
 
 // Events and their corresponding property names.
 var eventTypes = {
   compositionEnd: {
@@ -1052,17 +1385,17 @@ var CompositionEventPlugin = {
       EventPropagators.accumulateTwoPhaseDispatches(event);
       return event;
     }
   }
 };
 
 module.exports = CompositionEventPlugin;
 
-},{"./EventConstants":15,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":56,"./SyntheticCompositionEvent":87,"./getTextContentAccessor":121,"./keyOf":132}],8:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactInputSelection":63,"./SyntheticCompositionEvent":94,"./getTextContentAccessor":129,"./keyOf":141}],10:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -1078,16 +1411,17 @@ module.exports = CompositionEventPlugin;
  */
 
 "use strict";
 
 var Danger = _dereq_("./Danger");
 var ReactMultiChildUpdateTypes = _dereq_("./ReactMultiChildUpdateTypes");
 
 var getTextContentAccessor = _dereq_("./getTextContentAccessor");
+var invariant = _dereq_("./invariant");
 
 /**
  * The DOM property to use when setting text content.
  *
  * @type {string}
  * @private
  */
 var textContentAccessor = getTextContentAccessor();
@@ -1096,30 +1430,24 @@ var textContentAccessor = getTextContent
  * Inserts `childNode` as a child of `parentNode` at the `index`.
  *
  * @param {DOMElement} parentNode Parent node in which to insert.
  * @param {DOMElement} childNode Child node to insert.
  * @param {number} index Index at which to insert the child.
  * @internal
  */
 function insertChildAt(parentNode, childNode, index) {
-  var childNodes = parentNode.childNodes;
-  if (childNodes[index] === childNode) {
-    return;
-  }
-  // If `childNode` is already a child of `parentNode`, remove it so that
-  // computing `childNodes[index]` takes into account the removal.
-  if (childNode.parentNode === parentNode) {
-    parentNode.removeChild(childNode);
-  }
-  if (index >= childNodes.length) {
-    parentNode.appendChild(childNode);
-  } else {
-    parentNode.insertBefore(childNode, childNodes[index]);
-  }
+  // By exploiting arrays returning `undefined` for an undefined index, we can
+  // rely exclusively on `insertBefore(node, null)` instead of also using
+  // `appendChild(node)`. However, using `undefined` is not allowed by all
+  // browsers so we must replace it with `null`.
+  parentNode.insertBefore(
+    childNode,
+    parentNode.childNodes[index] || null
+  );
 }
 
 var updateTextContent;
 if (textContentAccessor === 'textContent') {
   /**
    * Sets the text content of `node` to `text`.
    *
    * @param {DOMElement} node Node to change
@@ -1174,16 +1502,28 @@ var DOMChildrenOperations = {
 
     for (var i = 0; update = updates[i]; i++) {
       if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
           update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
         var updatedIndex = update.fromIndex;
         var updatedChild = update.parentNode.childNodes[updatedIndex];
         var parentID = update.parentID;
 
+        ("production" !== "development" ? invariant(
+          updatedChild,
+          'processUpdates(): Unable to find child %s of element. This ' +
+          'probably means the DOM was unexpectedly mutated (e.g., by the ' +
+          'browser), usually due to forgetting a <tbody> when using tables, ' +
+          'nesting <p> or <a> tags, or using non-SVG elements in an <svg> '+
+          'parent. Try inspecting the child nodes of the element with React ' +
+          'ID `%s`.',
+          updatedIndex,
+          parentID
+        ) : invariant(updatedChild));
+
         initialChildren = initialChildren || {};
         initialChildren[parentID] = initialChildren[parentID] || [];
         initialChildren[parentID][updatedIndex] = updatedChild;
 
         updatedChildren = updatedChildren || [];
         updatedChildren.push(updatedChild);
       }
     }
@@ -1225,17 +1565,17 @@ var DOMChildrenOperations = {
       }
     }
   }
 
 };
 
 module.exports = DOMChildrenOperations;
 
-},{"./Danger":11,"./ReactMultiChildUpdateTypes":63,"./getTextContentAccessor":121}],9:[function(_dereq_,module,exports){
+},{"./Danger":13,"./ReactMultiChildUpdateTypes":69,"./getTextContentAccessor":129,"./invariant":134}],11:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -1260,17 +1600,19 @@ var DOMPropertyInjection = {
   /**
    * Mapping from normalized, camelcased property names to a configuration that
    * specifies how the associated DOM property should be accessed or rendered.
    */
   MUST_USE_ATTRIBUTE: 0x1,
   MUST_USE_PROPERTY: 0x2,
   HAS_SIDE_EFFECTS: 0x4,
   HAS_BOOLEAN_VALUE: 0x8,
-  HAS_POSITIVE_NUMERIC_VALUE: 0x10,
+  HAS_NUMERIC_VALUE: 0x10,
+  HAS_POSITIVE_NUMERIC_VALUE: 0x20 | 0x10,
+  HAS_OVERLOADED_BOOLEAN_VALUE: 0x40,
 
   /**
    * Inject some specialized knowledge about the DOM. This takes a config object
    * with the following properties:
    *
    * isCustomAttribute: function that given an attribute name will return true
    * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
    * attributes where it's impossible to enumerate all of the possible
@@ -1301,77 +1643,88 @@ var DOMPropertyInjection = {
     if (domPropertyConfig.isCustomAttribute) {
       DOMProperty._isCustomAttributeFunctions.push(
         domPropertyConfig.isCustomAttribute
       );
     }
 
     for (var propName in Properties) {
       ("production" !== "development" ? invariant(
-        !DOMProperty.isStandardName[propName],
+        !DOMProperty.isStandardName.hasOwnProperty(propName),
         'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' +
         '\'%s\' which has already been injected. You may be accidentally ' +
         'injecting the same DOM property config twice, or you may be ' +
         'injecting two configs that have conflicting property names.',
         propName
-      ) : invariant(!DOMProperty.isStandardName[propName]));
+      ) : invariant(!DOMProperty.isStandardName.hasOwnProperty(propName)));
 
       DOMProperty.isStandardName[propName] = true;
 
       var lowerCased = propName.toLowerCase();
       DOMProperty.getPossibleStandardName[lowerCased] = propName;
 
-      var attributeName = DOMAttributeNames[propName];
-      if (attributeName) {
+      if (DOMAttributeNames.hasOwnProperty(propName)) {
+        var attributeName = DOMAttributeNames[propName];
         DOMProperty.getPossibleStandardName[attributeName] = propName;
-      }
-
-      DOMProperty.getAttributeName[propName] = attributeName || lowerCased;
+        DOMProperty.getAttributeName[propName] = attributeName;
+      } else {
+        DOMProperty.getAttributeName[propName] = lowerCased;
+      }
 
       DOMProperty.getPropertyName[propName] =
-        DOMPropertyNames[propName] || propName;
-
-      var mutationMethod = DOMMutationMethods[propName];
-      if (mutationMethod) {
-        DOMProperty.getMutationMethod[propName] = mutationMethod;
+        DOMPropertyNames.hasOwnProperty(propName) ?
+          DOMPropertyNames[propName] :
+          propName;
+
+      if (DOMMutationMethods.hasOwnProperty(propName)) {
+        DOMProperty.getMutationMethod[propName] = DOMMutationMethods[propName];
+      } else {
+        DOMProperty.getMutationMethod[propName] = null;
       }
 
       var propConfig = Properties[propName];
       DOMProperty.mustUseAttribute[propName] =
         propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE;
       DOMProperty.mustUseProperty[propName] =
         propConfig & DOMPropertyInjection.MUST_USE_PROPERTY;
       DOMProperty.hasSideEffects[propName] =
         propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS;
       DOMProperty.hasBooleanValue[propName] =
         propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE;
+      DOMProperty.hasNumericValue[propName] =
+        propConfig & DOMPropertyInjection.HAS_NUMERIC_VALUE;
       DOMProperty.hasPositiveNumericValue[propName] =
         propConfig & DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE;
+      DOMProperty.hasOverloadedBooleanValue[propName] =
+        propConfig & DOMPropertyInjection.HAS_OVERLOADED_BOOLEAN_VALUE;
 
       ("production" !== "development" ? invariant(
         !DOMProperty.mustUseAttribute[propName] ||
           !DOMProperty.mustUseProperty[propName],
         'DOMProperty: Cannot require using both attribute and property: %s',
         propName
       ) : invariant(!DOMProperty.mustUseAttribute[propName] ||
         !DOMProperty.mustUseProperty[propName]));
       ("production" !== "development" ? invariant(
         DOMProperty.mustUseProperty[propName] ||
           !DOMProperty.hasSideEffects[propName],
         'DOMProperty: Properties that have side effects must use property: %s',
         propName
       ) : invariant(DOMProperty.mustUseProperty[propName] ||
         !DOMProperty.hasSideEffects[propName]));
       ("production" !== "development" ? invariant(
-        !DOMProperty.hasBooleanValue[propName] ||
-          !DOMProperty.hasPositiveNumericValue[propName],
-        'DOMProperty: Cannot have both boolean and positive numeric value: %s',
+        !!DOMProperty.hasBooleanValue[propName] +
+          !!DOMProperty.hasNumericValue[propName] +
+          !!DOMProperty.hasOverloadedBooleanValue[propName] <= 1,
+        'DOMProperty: Value can be one of boolean, overloaded boolean, or ' +
+        'numeric value, but not a combination: %s',
         propName
-      ) : invariant(!DOMProperty.hasBooleanValue[propName] ||
-        !DOMProperty.hasPositiveNumericValue[propName]));
+      ) : invariant(!!DOMProperty.hasBooleanValue[propName] +
+        !!DOMProperty.hasNumericValue[propName] +
+        !!DOMProperty.hasOverloadedBooleanValue[propName] <= 1));
     }
   }
 };
 var defaultValueCache = {};
 
 /**
  * DOMProperty exports lookup objects that can be used like functions:
  *
@@ -1446,23 +1799,38 @@ var DOMProperty = {
 
   /**
    * Whether the property should be removed when set to a falsey value.
    * @type {Object}
    */
   hasBooleanValue: {},
 
   /**
+   * Whether the property must be numeric or parse as a
+   * numeric and should be removed when set to a falsey value.
+   * @type {Object}
+   */
+  hasNumericValue: {},
+
+  /**
    * Whether the property must be positive numeric or parse as a positive
    * numeric and should be removed when set to a falsey value.
    * @type {Object}
    */
   hasPositiveNumericValue: {},
 
   /**
+   * Whether the property can be used as a flag as well as with a value. Removed
+   * when strictly equal to false; present without a value when strictly equal
+   * to true; present with a value otherwise.
+   * @type {Object}
+   */
+  hasOverloadedBooleanValue: {},
+
+  /**
    * All of the isCustomAttribute() functions that have been injected.
    */
   _isCustomAttributeFunctions: [],
 
   /**
    * Checks whether a property name is a custom attribute.
    * @method
    */
@@ -1497,17 +1865,17 @@ var DOMProperty = {
     return nodeDefaults[prop];
   },
 
   injection: DOMPropertyInjection
 };
 
 module.exports = DOMProperty;
 
-},{"./invariant":125}],10:[function(_dereq_,module,exports){
+},{"./invariant":134}],12:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -1527,44 +1895,52 @@ module.exports = DOMProperty;
 var DOMProperty = _dereq_("./DOMProperty");
 
 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser");
 var memoizeStringOnly = _dereq_("./memoizeStringOnly");
 var warning = _dereq_("./warning");
 
 function shouldIgnoreValue(name, value) {
   return value == null ||
-    DOMProperty.hasBooleanValue[name] && !value ||
-    DOMProperty.hasPositiveNumericValue[name] && (isNaN(value) || value < 1);
+    (DOMProperty.hasBooleanValue[name] && !value) ||
+    (DOMProperty.hasNumericValue[name] && isNaN(value)) ||
+    (DOMProperty.hasPositiveNumericValue[name] && (value < 1)) ||
+    (DOMProperty.hasOverloadedBooleanValue[name] && value === false);
 }
 
 var processAttributeNameAndPrefix = memoizeStringOnly(function(name) {
   return escapeTextForBrowser(name) + '="';
 });
 
 if ("production" !== "development") {
   var reactProps = {
     children: true,
     dangerouslySetInnerHTML: true,
     key: true,
     ref: true
   };
   var warnedProperties = {};
 
   var warnUnknownProperty = function(name) {
-    if (reactProps[name] || warnedProperties[name]) {
+    if (reactProps.hasOwnProperty(name) && reactProps[name] ||
+        warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
       return;
     }
 
     warnedProperties[name] = true;
     var lowerCasedName = name.toLowerCase();
 
     // data-* attributes should be lowercase; suggest the lowercase version
-    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ?
-      lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName];
+    var standardName = (
+      DOMProperty.isCustomAttribute(lowerCasedName) ?
+        lowerCasedName :
+      DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
+        DOMProperty.getPossibleStandardName[lowerCasedName] :
+        null
+    );
 
     // For now, only warn when we have a suggested correction. This prevents
     // logging too much when using transferPropsTo.
     ("production" !== "development" ? warning(
       standardName == null,
       'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
     ) : null);
 
@@ -1590,22 +1966,24 @@ var DOMPropertyOperations = {
   /**
    * Creates markup for a property.
    *
    * @param {string} name
    * @param {*} value
    * @return {?string} Markup string, or null if the property was invalid.
    */
   createMarkupForProperty: function(name, value) {
-    if (DOMProperty.isStandardName[name]) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
       if (shouldIgnoreValue(name, value)) {
         return '';
       }
       var attributeName = DOMProperty.getAttributeName[name];
-      if (DOMProperty.hasBooleanValue[name]) {
+      if (DOMProperty.hasBooleanValue[name] ||
+          (DOMProperty.hasOverloadedBooleanValue[name] && value === true)) {
         return escapeTextForBrowser(attributeName);
       }
       return processAttributeNameAndPrefix(attributeName) +
         escapeTextForBrowser(value) + '"';
     } else if (DOMProperty.isCustomAttribute(name)) {
       if (value == null) {
         return '';
       }
@@ -1620,49 +1998,51 @@ var DOMPropertyOperations = {
   /**
    * Sets the value for a property on a node.
    *
    * @param {DOMElement} node
    * @param {string} name
    * @param {*} value
    */
   setValueForProperty: function(node, name, value) {
-    if (DOMProperty.isStandardName[name]) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
       var mutationMethod = DOMProperty.getMutationMethod[name];
       if (mutationMethod) {
         mutationMethod(node, value);
       } else if (shouldIgnoreValue(name, value)) {
         this.deleteValueForProperty(node, name);
       } else if (DOMProperty.mustUseAttribute[name]) {
         node.setAttribute(DOMProperty.getAttributeName[name], '' + value);
       } else {
         var propName = DOMProperty.getPropertyName[name];
         if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) {
           node[propName] = value;
         }
       }
     } else if (DOMProperty.isCustomAttribute(name)) {
       if (value == null) {
-        node.removeAttribute(DOMProperty.getAttributeName[name]);
+        node.removeAttribute(name);
       } else {
         node.setAttribute(name, '' + value);
       }
     } else if ("production" !== "development") {
       warnUnknownProperty(name);
     }
   },
 
   /**
    * Deletes the value for a property on a node.
    *
    * @param {DOMElement} node
    * @param {string} name
    */
   deleteValueForProperty: function(node, name) {
-    if (DOMProperty.isStandardName[name]) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
       var mutationMethod = DOMProperty.getMutationMethod[name];
       if (mutationMethod) {
         mutationMethod(node, undefined);
       } else if (DOMProperty.mustUseAttribute[name]) {
         node.removeAttribute(DOMProperty.getAttributeName[name]);
       } else {
         var propName = DOMProperty.getPropertyName[name];
         var defaultValue = DOMProperty.getDefaultValueForProperty(
@@ -1680,17 +2060,17 @@ var DOMPropertyOperations = {
       warnUnknownProperty(name);
     }
   }
 
 };
 
 module.exports = DOMPropertyOperations;
 
-},{"./DOMProperty":9,"./escapeTextForBrowser":111,"./memoizeStringOnly":133,"./warning":148}],11:[function(_dereq_,module,exports){
+},{"./DOMProperty":11,"./escapeTextForBrowser":118,"./memoizeStringOnly":143,"./warning":158}],13:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -1869,215 +2249,17 @@ var Danger = {
     var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
     oldChild.parentNode.replaceChild(newChild, oldChild);
   }
 
 };
 
 module.exports = Danger;
 
-},{"./ExecutionEnvironment":21,"./createNodesFromMarkup":105,"./emptyFunction":109,"./getMarkupWrap":118,"./invariant":125}],12:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2014 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @providesModule DefaultDOMPropertyConfig
- */
-
-/*jslint bitwise: true*/
-
-"use strict";
-
-var DOMProperty = _dereq_("./DOMProperty");
-
-var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE;
-var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
-var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
-var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS;
-var HAS_POSITIVE_NUMERIC_VALUE =
-  DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;
-
-var DefaultDOMPropertyConfig = {
-  isCustomAttribute: RegExp.prototype.test.bind(
-    /^(data|aria)-[a-z_][a-z\d_.\-]*$/
-  ),
-  Properties: {
-    /**
-     * Standard Properties
-     */
-    accept: null,
-    accessKey: null,
-    action: null,
-    allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
-    allowTransparency: MUST_USE_ATTRIBUTE,
-    alt: null,
-    async: HAS_BOOLEAN_VALUE,
-    autoComplete: null,
-    // autoFocus is polyfilled/normalized by AutoFocusMixin
-    // autoFocus: HAS_BOOLEAN_VALUE,
-    autoPlay: HAS_BOOLEAN_VALUE,
-    cellPadding: null,
-    cellSpacing: null,
-    charSet: MUST_USE_ATTRIBUTE,
-    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    className: MUST_USE_PROPERTY,
-    cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
-    colSpan: null,
-    content: null,
-    contentEditable: null,
-    contextMenu: MUST_USE_ATTRIBUTE,
-    controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    crossOrigin: null,
-    data: null, // For `<object />` acts as `src`.
-    dateTime: MUST_USE_ATTRIBUTE,
-    defer: HAS_BOOLEAN_VALUE,
-    dir: null,
-    disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
-    download: null,
-    draggable: null,
-    encType: null,
-    form: MUST_USE_ATTRIBUTE,
-    formNoValidate: HAS_BOOLEAN_VALUE,
-    frameBorder: MUST_USE_ATTRIBUTE,
-    height: MUST_USE_ATTRIBUTE,
-    hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
-    href: null,
-    hrefLang: null,
-    htmlFor: null,
-    httpEquiv: null,
-    icon: null,
-    id: MUST_USE_PROPERTY,
-    label: null,
-    lang: null,
-    list: null,
-    loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    max: null,
-    maxLength: MUST_USE_ATTRIBUTE,
-    mediaGroup: null,
-    method: null,
-    min: null,
-    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    name: null,
-    noValidate: HAS_BOOLEAN_VALUE,
-    pattern: null,
-    placeholder: null,
-    poster: null,
-    preload: null,
-    radioGroup: null,
-    readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    rel: null,
-    required: HAS_BOOLEAN_VALUE,
-    role: MUST_USE_ATTRIBUTE,
-    rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
-    rowSpan: null,
-    sandbox: null,
-    scope: null,
-    scrollLeft: MUST_USE_PROPERTY,
-    scrollTop: MUST_USE_PROPERTY,
-    seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
-    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
-    size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
-    span: HAS_POSITIVE_NUMERIC_VALUE,
-    spellCheck: null,
-    src: null,
-    srcDoc: MUST_USE_PROPERTY,
-    srcSet: null,
-    step: null,
-    style: null,
-    tabIndex: null,
-    target: null,
-    title: null,
-    type: null,
-    value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
-    width: MUST_USE_ATTRIBUTE,
-    wmode: MUST_USE_ATTRIBUTE,
-
-    /**
-     * Non-standard Properties
-     */
-    autoCapitalize: null, // Supported in Mobile Safari for keyboard hints
-    autoCorrect: null, // Supported in Mobile Safari for keyboard hints
-    property: null, // Supports OG in meta tags
-
-    /**
-     * SVG Properties
-     */
-    cx: MUST_USE_ATTRIBUTE,
-    cy: MUST_USE_ATTRIBUTE,
-    d: MUST_USE_ATTRIBUTE,
-    fill: MUST_USE_ATTRIBUTE,
-    fx: MUST_USE_ATTRIBUTE,
-    fy: MUST_USE_ATTRIBUTE,
-    gradientTransform: MUST_USE_ATTRIBUTE,
-    gradientUnits: MUST_USE_ATTRIBUTE,
-    offset: MUST_USE_ATTRIBUTE,
-    points: MUST_USE_ATTRIBUTE,
-    r: MUST_USE_ATTRIBUTE,
-    rx: MUST_USE_ATTRIBUTE,
-    ry: MUST_USE_ATTRIBUTE,
-    spreadMethod: MUST_USE_ATTRIBUTE,
-    stopColor: MUST_USE_ATTRIBUTE,
-    stopOpacity: MUST_USE_ATTRIBUTE,
-    stroke: MUST_USE_ATTRIBUTE,
-    strokeLinecap: MUST_USE_ATTRIBUTE,
-    strokeWidth: MUST_USE_ATTRIBUTE,
-    textAnchor: MUST_USE_ATTRIBUTE,
-    transform: MUST_USE_ATTRIBUTE,
-    version: MUST_USE_ATTRIBUTE,
-    viewBox: MUST_USE_ATTRIBUTE,
-    x1: MUST_USE_ATTRIBUTE,
-    x2: MUST_USE_ATTRIBUTE,
-    x: MUST_USE_ATTRIBUTE,
-    y1: MUST_USE_ATTRIBUTE,
-    y2: MUST_USE_ATTRIBUTE,
-    y: MUST_USE_ATTRIBUTE
-  },
-  DOMAttributeNames: {
-    className: 'class',
-    gradientTransform: 'gradientTransform',
-    gradientUnits: 'gradientUnits',
-    htmlFor: 'for',
-    spreadMethod: 'spreadMethod',
-    stopColor: 'stop-color',
-    stopOpacity: 'stop-opacity',
-    strokeLinecap: 'stroke-linecap',
-    strokeWidth: 'stroke-width',
-    textAnchor: 'text-anchor',
-    viewBox: 'viewBox'
-  },
-  DOMPropertyNames: {
-    autoCapitalize: 'autocapitalize',
-    autoComplete: 'autocomplete',
-    autoCorrect: 'autocorrect',
-    autoFocus: 'autofocus',
-    autoPlay: 'autoplay',
-    encType: 'enctype',
-    hrefLang: 'hreflang',
-    radioGroup: 'radiogroup',
-    spellCheck: 'spellcheck',
-    srcDoc: 'srcdoc',
-    srcSet: 'srcset'
-  }
-};
-
-module.exports = DefaultDOMPropertyConfig;
-
-},{"./DOMProperty":9}],13:[function(_dereq_,module,exports){
+},{"./ExecutionEnvironment":22,"./createNodesFromMarkup":113,"./emptyFunction":116,"./getMarkupWrap":126,"./invariant":134}],14:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -2107,23 +2289,24 @@ module.exports = DefaultDOMPropertyConfi
 var DefaultEventPluginOrder = [
   keyOf({ResponderEventPlugin: null}),
   keyOf({SimpleEventPlugin: null}),
   keyOf({TapEventPlugin: null}),
   keyOf({EnterLeaveEventPlugin: null}),
   keyOf({ChangeEventPlugin: null}),
   keyOf({SelectEventPlugin: null}),
   keyOf({CompositionEventPlugin: null}),
+  keyOf({BeforeInputEventPlugin: null}),
   keyOf({AnalyticsEventPlugin: null}),
   keyOf({MobileSafariClickEventPlugin: null})
 ];
 
 module.exports = DefaultEventPluginOrder;
 
-},{"./keyOf":132}],14:[function(_dereq_,module,exports){
+},{"./keyOf":141}],15:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -2260,17 +2443,17 @@ var EnterLeaveEventPlugin = {
 
     return extractedEvents;
   }
 
 };
 
 module.exports = EnterLeaveEventPlugin;
 
-},{"./EventConstants":15,"./EventPropagators":20,"./ReactMount":60,"./SyntheticMouseEvent":92,"./keyOf":132}],15:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./EventPropagators":21,"./ReactMount":67,"./SyntheticMouseEvent":100,"./keyOf":141}],16:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -2324,33 +2507,35 @@ var topLevelTypes = keyMirror({
   topMouseOut: null,
   topMouseOver: null,
   topMouseUp: null,
   topPaste: null,
   topReset: null,
   topScroll: null,
   topSelectionChange: null,
   topSubmit: null,
+  topTextInput: null,
   topTouchCancel: null,
   topTouchEnd: null,
   topTouchMove: null,
   topTouchStart: null,
   topWheel: null
 });
 
 var EventConstants = {
   topLevelTypes: topLevelTypes,
   PropagationPhases: PropagationPhases
 };
 
 module.exports = EventConstants;
 
-},{"./keyMirror":131}],16:[function(_dereq_,module,exports){
+},{"./keyMirror":140}],17:[function(_dereq_,module,exports){
 /**
  * @providesModule EventListener
+ * @typechecks
  */
 
 var emptyFunction = _dereq_("./emptyFunction");
 
 /**
  * Upstream version of event listener. Does not take into account specific
  * nature of platform.
  */
@@ -2370,17 +2555,17 @@ var EventListener = {
         remove: function() {
           target.removeEventListener(eventType, callback, false);
         }
       };
     } else if (target.attachEvent) {
       target.attachEvent('on' + eventType, callback);
       return {
         remove: function() {
-          target.detachEvent(eventType, callback);
+          target.detachEvent('on' + eventType, callback);
         }
       };
     }
   },
 
   /**
    * Listen to DOM events during the capture phase.
    *
@@ -2404,22 +2589,24 @@ var EventListener = {
     } else {
       target.addEventListener(eventType, callback, true);
       return {
         remove: function() {
           target.removeEventListener(eventType, callback, true);
         }
       };
     }
-  }
+  },
+
+  registerDefault: function() {}
 };
 
 module.exports = EventListener;
 
-},{"./emptyFunction":109}],17:[function(_dereq_,module,exports){
+},{"./emptyFunction":116}],18:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -2432,17 +2619,16 @@ module.exports = EventListener;
  *
  * @providesModule EventPluginHub
  */
 
 "use strict";
 
 var EventPluginRegistry = _dereq_("./EventPluginRegistry");
 var EventPluginUtils = _dereq_("./EventPluginUtils");
-var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
 
 var accumulate = _dereq_("./accumulate");
 var forEachAccumulated = _dereq_("./forEachAccumulated");
 var invariant = _dereq_("./invariant");
 var isEventSupported = _dereq_("./isEventSupported");
 var monitorCodeUse = _dereq_("./monitorCodeUse");
 
 /**
@@ -2567,20 +2753,16 @@ var EventPluginHub = {
    * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.
    *
    * @param {string} id ID of the DOM element.
    * @param {string} registrationName Name of listener (e.g. `onClick`).
    * @param {?function} listener The callback to store.
    */
   putListener: function(id, registrationName, listener) {
     ("production" !== "development" ? invariant(
-      ExecutionEnvironment.canUseDOM,
-      'Cannot call putListener() in a non-DOM environment.'
-    ) : invariant(ExecutionEnvironment.canUseDOM));
-    ("production" !== "development" ? invariant(
       !listener || typeof listener === 'function',
       'Expected %s listener to be a function, instead got type %s',
       registrationName, typeof listener
     ) : invariant(!listener || typeof listener === 'function'));
 
     if ("production" !== "development") {
       // IE8 has no API for event capturing and the `onScroll` event doesn't
       // bubble.
@@ -2706,17 +2888,17 @@ var EventPluginHub = {
   __getListenerBank: function() {
     return listenerBank;
   }
 
 };
 
 module.exports = EventPluginHub;
 
-},{"./EventPluginRegistry":18,"./EventPluginUtils":19,"./ExecutionEnvironment":21,"./accumulate":98,"./forEachAccumulated":114,"./invariant":125,"./isEventSupported":126,"./monitorCodeUse":138}],18:[function(_dereq_,module,exports){
+},{"./EventPluginRegistry":19,"./EventPluginUtils":20,"./accumulate":106,"./forEachAccumulated":121,"./invariant":134,"./isEventSupported":135,"./monitorCodeUse":148}],19:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -2799,21 +2981,21 @@ function recomputePluginOrdering() {
  *
  * @param {object} dispatchConfig Dispatch configuration for the event.
  * @param {object} PluginModule Plugin publishing the event.
  * @return {boolean} True if the event was successfully published.
  * @private
  */
 function publishEventForPlugin(dispatchConfig, PluginModule, eventName) {
   ("production" !== "development" ? invariant(
-    !EventPluginRegistry.eventNameDispatchConfigs[eventName],
+    !EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName),
     'EventPluginHub: More than one plugin attempted to publish the same ' +
     'event name, `%s`.',
     eventName
-  ) : invariant(!EventPluginRegistry.eventNameDispatchConfigs[eventName]));
+  ) : invariant(!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName)));
   EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;
 
   var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
   if (phasedRegistrationNames) {
     for (var phaseName in phasedRegistrationNames) {
       if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
         var phasedRegistrationName = phasedRegistrationNames[phaseName];
         publishRegistrationName(
@@ -2889,17 +3071,18 @@ var EventPluginRegistry = {
    *
    * @param {array} InjectedEventPluginOrder
    * @internal
    * @see {EventPluginHub.injection.injectEventPluginOrder}
    */
   injectEventPluginOrder: function(InjectedEventPluginOrder) {
     ("production" !== "development" ? invariant(
       !EventPluginOrder,
-      'EventPluginRegistry: Cannot inject event plugin ordering more than once.'
+      'EventPluginRegistry: Cannot inject event plugin ordering more than ' +
+      'once. You are likely trying to load more than one copy of React.'
     ) : invariant(!EventPluginOrder));
     // Clone the ordering so it cannot be dynamically mutated.
     EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);
     recomputePluginOrdering();
   },
 
   /**
    * Injects plugins to be used by `EventPluginHub`. The plugin names must be
@@ -2913,17 +3096,18 @@ var EventPluginRegistry = {
    */
   injectEventPluginsByName: function(injectedNamesToPlugins) {
     var isOrderingDirty = false;
     for (var pluginName in injectedNamesToPlugins) {
       if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
         continue;
       }
       var PluginModule = injectedNamesToPlugins[pluginName];
-      if (namesToPlugins[pluginName] !== PluginModule) {
+      if (!namesToPlugins.hasOwnProperty(pluginName) ||
+          namesToPlugins[pluginName] !== PluginModule) {
         ("production" !== "development" ? invariant(
           !namesToPlugins[pluginName],
           'EventPluginRegistry: Cannot inject two different event plugins ' +
           'using the same name, `%s`.',
           pluginName
         ) : invariant(!namesToPlugins[pluginName]));
         namesToPlugins[pluginName] = PluginModule;
         isOrderingDirty = true;
@@ -2989,17 +3173,17 @@ var EventPluginRegistry = {
       }
     }
   }
 
 };
 
 module.exports = EventPluginRegistry;
 
-},{"./invariant":125}],19:[function(_dereq_,module,exports){
+},{"./invariant":134}],20:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3127,17 +3311,17 @@ function executeDispatchesInOrder(event,
 
 /**
  * Standard/simple iteration through an event's collected dispatches, but stops
  * at the first dispatch execution returning true, and returns that id.
  *
  * @return id of the first dispatch execution who's listener returns true, or
  * null if no listener returned true.
  */
-function executeDispatchesInOrderStopAtTrue(event) {
+function executeDispatchesInOrderStopAtTrueImpl(event) {
   var dispatchListeners = event._dispatchListeners;
   var dispatchIDs = event._dispatchIDs;
   if ("production" !== "development") {
     validateEventDispatches(event);
   }
   if (Array.isArray(dispatchListeners)) {
     for (var i = 0; i < dispatchListeners.length; i++) {
       if (event.isPropagationStopped()) {
@@ -3152,16 +3336,26 @@ function executeDispatchesInOrderStopAtT
     if (dispatchListeners(event, dispatchIDs)) {
       return dispatchIDs;
     }
   }
   return null;
 }
 
 /**
+ * @see executeDispatchesInOrderStopAtTrueImpl
+ */
+function executeDispatchesInOrderStopAtTrue(event) {
+  var ret = executeDispatchesInOrderStopAtTrueImpl(event);
+  event._dispatchIDs = null;
+  event._dispatchListeners = null;
+  return ret;
+}
+
+/**
  * Execution of a "direct" dispatch - there must be at most one dispatch
  * accumulated on the event or it is considered an error. It doesn't really make
  * sense for an event with multiple dispatches (bubbled) to keep track of the
  * return values at each dispatch execution, but it does tend to make sense when
  * dealing with "direct" dispatches.
  *
  * @return The return value of executing the single dispatch.
  */
@@ -3205,17 +3399,17 @@ var EventPluginUtils = {
   executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
   hasDispatches: hasDispatches,
   injection: injection,
   useTouchEvents: false
 };
 
 module.exports = EventPluginUtils;
 
-},{"./EventConstants":15,"./invariant":125}],20:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./invariant":134}],21:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3350,17 +3544,17 @@ function accumulateDirectDispatches(even
 var EventPropagators = {
   accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
   accumulateDirectDispatches: accumulateDirectDispatches,
   accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
 };
 
 module.exports = EventPropagators;
 
-},{"./EventConstants":15,"./EventPluginHub":17,"./accumulate":98,"./forEachAccumulated":114}],21:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./EventPluginHub":18,"./accumulate":106,"./forEachAccumulated":121}],22:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3373,40 +3567,234 @@ module.exports = EventPropagators;
  *
  * @providesModule ExecutionEnvironment
  */
 
 /*jslint evil: true */
 
 "use strict";
 
-var canUseDOM = typeof window !== 'undefined';
+var canUseDOM = !!(
+  typeof window !== 'undefined' &&
+  window.document &&
+  window.document.createElement
+);
 
 /**
  * Simple, lightweight module assisting with the detection and context of
  * Worker. Helps avoid circular dependencies and allows code to reason about
  * whether or not they are in a Worker, even if they never include the main
  * `ReactWorker` dependency.
  */
 var ExecutionEnvironment = {
 
   canUseDOM: canUseDOM,
 
   canUseWorkers: typeof Worker !== 'undefined',
 
   canUseEventListeners:
-    canUseDOM && (window.addEventListener || window.attachEvent),
+    canUseDOM && !!(window.addEventListener || window.attachEvent),
+
+  canUseViewport: canUseDOM && !!window.screen,
 
   isInWorker: !canUseDOM // For now, this is true - might change in the future.
 
 };
 
 module.exports = ExecutionEnvironment;
 
-},{}],22:[function(_dereq_,module,exports){
+},{}],23:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule HTMLDOMPropertyConfig
+ */
+
+/*jslint bitwise: true*/
+
+"use strict";
+
+var DOMProperty = _dereq_("./DOMProperty");
+var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
+
+var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE;
+var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
+var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
+var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS;
+var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;
+var HAS_POSITIVE_NUMERIC_VALUE =
+  DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;
+var HAS_OVERLOADED_BOOLEAN_VALUE =
+  DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;
+
+var hasSVG;
+if (ExecutionEnvironment.canUseDOM) {
+  var implementation = document.implementation;
+  hasSVG = (
+    implementation &&
+    implementation.hasFeature &&
+    implementation.hasFeature(
+      'http://www.w3.org/TR/SVG11/feature#BasicStructure',
+      '1.1'
+    )
+  );
+}
+
+
+var HTMLDOMPropertyConfig = {
+  isCustomAttribute: RegExp.prototype.test.bind(
+    /^(data|aria)-[a-z_][a-z\d_.\-]*$/
+  ),
+  Properties: {
+    /**
+     * Standard Properties
+     */
+    accept: null,
+    accessKey: null,
+    action: null,
+    allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+    allowTransparency: MUST_USE_ATTRIBUTE,
+    alt: null,
+    async: HAS_BOOLEAN_VALUE,
+    autoComplete: null,
+    // autoFocus is polyfilled/normalized by AutoFocusMixin
+    // autoFocus: HAS_BOOLEAN_VALUE,
+    autoPlay: HAS_BOOLEAN_VALUE,
+    cellPadding: null,
+    cellSpacing: null,
+    charSet: MUST_USE_ATTRIBUTE,
+    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    // To set className on SVG elements, it's necessary to use .setAttribute;
+    // this works on HTML elements too in all browsers except IE8. Conveniently,
+    // IE8 doesn't support SVG and so we can simply use the attribute in
+    // browsers that support SVG and the property in browsers that don't,
+    // regardless of whether the element is HTML or SVG.
+    className: hasSVG ? MUST_USE_ATTRIBUTE : MUST_USE_PROPERTY,
+    cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
+    colSpan: null,
+    content: null,
+    contentEditable: null,
+    contextMenu: MUST_USE_ATTRIBUTE,
+    controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    coords: null,
+    crossOrigin: null,
+    data: null, // For `<object />` acts as `src`.
+    dateTime: MUST_USE_ATTRIBUTE,
+    defer: HAS_BOOLEAN_VALUE,
+    dir: null,
+    disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+    download: HAS_OVERLOADED_BOOLEAN_VALUE,
+    draggable: null,
+    encType: null,
+    form: MUST_USE_ATTRIBUTE,
+    formNoValidate: HAS_BOOLEAN_VALUE,
+    frameBorder: MUST_USE_ATTRIBUTE,
+    height: MUST_USE_ATTRIBUTE,
+    hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+    href: null,
+    hrefLang: null,
+    htmlFor: null,
+    httpEquiv: null,
+    icon: null,
+    id: MUST_USE_PROPERTY,
+    label: null,
+    lang: null,
+    list: null,
+    loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    max: null,
+    maxLength: MUST_USE_ATTRIBUTE,
+    mediaGroup: null,
+    method: null,
+    min: null,
+    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    name: null,
+    noValidate: HAS_BOOLEAN_VALUE,
+    pattern: null,
+    placeholder: null,
+    poster: null,
+    preload: null,
+    radioGroup: null,
+    readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    rel: null,
+    required: HAS_BOOLEAN_VALUE,
+    role: MUST_USE_ATTRIBUTE,
+    rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
+    rowSpan: null,
+    sandbox: null,
+    scope: null,
+    scrollLeft: MUST_USE_PROPERTY,
+    scrolling: null,
+    scrollTop: MUST_USE_PROPERTY,
+    seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+    shape: null,
+    size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
+    span: HAS_POSITIVE_NUMERIC_VALUE,
+    spellCheck: null,
+    src: null,
+    srcDoc: MUST_USE_PROPERTY,
+    srcSet: null,
+    start: HAS_NUMERIC_VALUE,
+    step: null,
+    style: null,
+    tabIndex: null,
+    target: null,
+    title: null,
+    type: null,
+    useMap: null,
+    value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
+    width: MUST_USE_ATTRIBUTE,
+    wmode: MUST_USE_ATTRIBUTE,
+
+    /**
+     * Non-standard Properties
+     */
+    autoCapitalize: null, // Supported in Mobile Safari for keyboard hints
+    autoCorrect: null, // Supported in Mobile Safari for keyboard hints
+    itemProp: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html
+    itemScope: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, // Microdata: http://schema.org/docs/gs.html
+    itemType: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html
+    property: null // Supports OG in meta tags
+  },
+  DOMAttributeNames: {
+    className: 'class',
+    htmlFor: 'for',
+    httpEquiv: 'http-equiv'
+  },
+  DOMPropertyNames: {
+    autoCapitalize: 'autocapitalize',
+    autoComplete: 'autocomplete',
+    autoCorrect: 'autocorrect',
+    autoFocus: 'autofocus',
+    autoPlay: 'autoplay',
+    encType: 'enctype',
+    hrefLang: 'hreflang',
+    radioGroup: 'radiogroup',
+    spellCheck: 'spellcheck',
+    srcDoc: 'srcdoc',
+    srcSet: 'srcset'
+  }
+};
+
+module.exports = HTMLDOMPropertyConfig;
+
+},{"./DOMProperty":11,"./ExecutionEnvironment":22}],24:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3444,17 +3832,17 @@ var LinkedStateMixin = {
       this.state[key],
       ReactStateSetters.createStateKeySetter(this, key)
     );
   }
 };
 
 module.exports = LinkedStateMixin;
 
-},{"./ReactLink":58,"./ReactStateSetters":75}],23:[function(_dereq_,module,exports){
+},{"./ReactLink":65,"./ReactStateSetters":81}],25:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3469,33 +3857,32 @@ module.exports = LinkedStateMixin;
  * @typechecks static-only
  */
 
 "use strict";
 
 var ReactPropTypes = _dereq_("./ReactPropTypes");
 
 var invariant = _dereq_("./invariant");
-var warning = _dereq_("./warning");
 
 var hasReadOnlyValue = {
   'button': true,
   'checkbox': true,
   'image': true,
   'hidden': true,
   'radio': true,
   'reset': true,
   'submit': true
 };
 
 function _assertSingleLink(input) {
   ("production" !== "development" ? invariant(
-      input.props.checkedLink == null || input.props.valueLink == null,
-      'Cannot provide a checkedLink and a valueLink. If you want to use ' +
-      'checkedLink, you probably don\'t want to use valueLink and vice versa.'
+    input.props.checkedLink == null || input.props.valueLink == null,
+    'Cannot provide a checkedLink and a valueLink. If you want to use ' +
+    'checkedLink, you probably don\'t want to use valueLink and vice versa.'
   ) : invariant(input.props.checkedLink == null || input.props.valueLink == null));
 }
 function _assertValueLink(input) {
   _assertSingleLink(input);
   ("production" !== "development" ? invariant(
     input.props.value == null && input.props.onChange == null,
     'Cannot provide a valueLink and a value or onChange event. If you want ' +
     'to use value or onChange, you probably don\'t want to use valueLink.'
@@ -3531,43 +3918,43 @@ function _handleLinkedCheckChange(e) {
 /**
  * Provide a linked `value` attribute for controlled forms. You should not use
  * this outside of the ReactDOM controlled form components.
  */
 var LinkedValueUtils = {
   Mixin: {
     propTypes: {
       value: function(props, propName, componentName) {
-        if ("production" !== "development") {
-          ("production" !== "development" ? warning(
-            !props[propName] ||
+        if (!props[propName] ||
             hasReadOnlyValue[props.type] ||
             props.onChange ||
             props.readOnly ||
-            props.disabled,
-            'You provided a `value` prop to a form field without an ' +
-            '`onChange` handler. This will render a read-only field. If ' +
-            'the field should be mutable use `defaultValue`. Otherwise, ' +
-            'set either `onChange` or `readOnly`.'
-          ) : null);
-        }
+            props.disabled) {
+          return;
+        }
+        return new Error(
+          'You provided a `value` prop to a form field without an ' +
+          '`onChange` handler. This will render a read-only field. If ' +
+          'the field should be mutable use `defaultValue`. Otherwise, ' +
+          'set either `onChange` or `readOnly`.'
+        );
       },
       checked: function(props, propName, componentName) {
-        if ("production" !== "development") {
-          ("production" !== "development" ? warning(
-            !props[propName] ||
+        if (!props[propName] ||
             props.onChange ||
             props.readOnly ||
-            props.disabled,
-            'You provided a `checked` prop to a form field without an ' +
-            '`onChange` handler. This will render a read-only field. If ' +
-            'the field should be mutable use `defaultChecked`. Otherwise, ' +
-            'set either `onChange` or `readOnly`.'
-          ) : null);
-        }
+            props.disabled) {
+          return;
+        }
+        return new Error(
+          'You provided a `checked` prop to a form field without an ' +
+          '`onChange` handler. This will render a read-only field. If ' +
+          'the field should be mutable use `defaultChecked`. Otherwise, ' +
+          'set either `onChange` or `readOnly`.'
+        );
       },
       onChange: ReactPropTypes.func
     }
   },
 
   /**
    * @param {ReactComponent} input Form component
    * @return {*} current value of the input either from value prop or link.
@@ -3606,17 +3993,71 @@ var LinkedValueUtils = {
       return _handleLinkedCheckChange;
     }
     return input.props.onChange;
   }
 };
 
 module.exports = LinkedValueUtils;
 
-},{"./ReactPropTypes":69,"./invariant":125,"./warning":148}],24:[function(_dereq_,module,exports){
+},{"./ReactPropTypes":75,"./invariant":134}],26:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule LocalEventTrapMixin
+ */
+
+"use strict";
+
+var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
+
+var accumulate = _dereq_("./accumulate");
+var forEachAccumulated = _dereq_("./forEachAccumulated");
+var invariant = _dereq_("./invariant");
+
+function remove(event) {
+  event.remove();
+}
+
+var LocalEventTrapMixin = {
+  trapBubbledEvent:function(topLevelType, handlerBaseName) {
+    ("production" !== "development" ? invariant(this.isMounted(), 'Must be mounted to trap events') : invariant(this.isMounted()));
+    var listener = ReactBrowserEventEmitter.trapBubbledEvent(
+      topLevelType,
+      handlerBaseName,
+      this.getDOMNode()
+    );
+    this._localEventListeners = accumulate(this._localEventListeners, listener);
+  },
+
+  // trapCapturedEvent would look nearly identical. We don't implement that
+  // method because it isn't currently needed.
+
+  componentWillUnmount:function() {
+    if (this._localEventListeners) {
+      forEachAccumulated(this._localEventListeners, remove);
+    }
+  }
+};
+
+module.exports = LocalEventTrapMixin;
+
+},{"./ReactBrowserEventEmitter":31,"./accumulate":106,"./forEachAccumulated":121,"./invariant":134}],27:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3671,17 +4112,17 @@ var MobileSafariClickEventPlugin = {
       }
     }
   }
 
 };
 
 module.exports = MobileSafariClickEventPlugin;
 
-},{"./EventConstants":15,"./emptyFunction":109}],25:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./emptyFunction":116}],28:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3792,17 +4233,17 @@ var PooledClass = {
   oneArgumentPooler: oneArgumentPooler,
   twoArgumentPooler: twoArgumentPooler,
   threeArgumentPooler: threeArgumentPooler,
   fiveArgumentPooler: fiveArgumentPooler
 };
 
 module.exports = PooledClass;
 
-},{"./invariant":125}],26:[function(_dereq_,module,exports){
+},{"./invariant":134}],29:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3820,16 +4261,17 @@ module.exports = PooledClass;
 
 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
 var EventPluginUtils = _dereq_("./EventPluginUtils");
 var ReactChildren = _dereq_("./ReactChildren");
 var ReactComponent = _dereq_("./ReactComponent");
 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
 var ReactContext = _dereq_("./ReactContext");
 var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+var ReactDescriptor = _dereq_("./ReactDescriptor");
 var ReactDOM = _dereq_("./ReactDOM");
 var ReactDOMComponent = _dereq_("./ReactDOMComponent");
 var ReactDefaultInjection = _dereq_("./ReactDefaultInjection");
 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
 var ReactMount = _dereq_("./ReactMount");
 var ReactMultiChild = _dereq_("./ReactMultiChild");
 var ReactPerf = _dereq_("./ReactPerf");
 var ReactPropTypes = _dereq_("./ReactPropTypes");
@@ -3839,37 +4281,42 @@ var ReactTextComponent = _dereq_("./Reac
 var onlyChild = _dereq_("./onlyChild");
 
 ReactDefaultInjection.inject();
 
 var React = {
   Children: {
     map: ReactChildren.map,
     forEach: ReactChildren.forEach,
+    count: ReactChildren.count,
     only: onlyChild
   },
   DOM: ReactDOM,
   PropTypes: ReactPropTypes,
   initializeTouchEvents: function(shouldUseTouch) {
     EventPluginUtils.useTouchEvents = shouldUseTouch;
   },
   createClass: ReactCompositeComponent.createClass,
+  createDescriptor: function(type, props, children) {
+    var args = Array.prototype.slice.call(arguments, 1);
+    return type.apply(null, args);
+  },
   constructAndRenderComponent: ReactMount.constructAndRenderComponent,
   constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID,
   renderComponent: ReactPerf.measure(
     'React',
     'renderComponent',
     ReactMount.renderComponent
   ),
   renderComponentToString: ReactServerRendering.renderComponentToString,
   renderComponentToStaticMarkup:
     ReactServerRendering.renderComponentToStaticMarkup,
   unmountComponentAtNode: ReactMount.unmountComponentAtNode,
-  isValidClass: ReactCompositeComponent.isValidClass,
-  isValidComponent: ReactComponent.isValidComponent,
+  isValidClass: ReactDescriptor.isValidFactory,
+  isValidComponent: ReactDescriptor.isValidDescriptor,
   withContext: ReactContext.withContext,
   __internals: {
     Component: ReactComponent,
     CurrentOwner: ReactCurrentOwner,
     DOMComponent: ReactDOMComponent,
     DOMPropertyOperations: DOMPropertyOperations,
     InstanceHandles: ReactInstanceHandles,
     Mount: ReactMount,
@@ -3882,26 +4329,54 @@ if ("production" !== "development") {
   var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
   if (ExecutionEnvironment.canUseDOM &&
       window.top === window.self &&
       navigator.userAgent.indexOf('Chrome') > -1) {
     console.debug(
       'Download the React DevTools for a better development experience: ' +
       'http://fb.me/react-devtools'
     );
+
+    var expectedFeatures = [
+      // shims
+      Array.isArray,
+      Array.prototype.every,
+      Array.prototype.forEach,
+      Array.prototype.indexOf,
+      Array.prototype.map,
+      Date.now,
+      Function.prototype.bind,
+      Object.keys,
+      String.prototype.split,
+      String.prototype.trim,
+
+      // shams
+      Object.create,
+      Object.freeze
+    ];
+
+    for (var i in expectedFeatures) {
+      if (!expectedFeatures[i]) {
+        console.error(
+          'One or more ES5 shim/shams expected by React are not available: ' +
+          'http://fb.me/react-warning-polyfills'
+        );
+        break;
+      }
+    }
   }
 }
 
 // Version exists only in the open-source version of React, not in Facebook's
 // internal version.
-React.version = '0.10.0';
+React.version = '0.11.1';
 
 module.exports = React;
 
-},{"./DOMPropertyOperations":10,"./EventPluginUtils":19,"./ExecutionEnvironment":21,"./ReactChildren":30,"./ReactComponent":31,"./ReactCompositeComponent":33,"./ReactContext":34,"./ReactCurrentOwner":35,"./ReactDOM":36,"./ReactDOMComponent":38,"./ReactDefaultInjection":48,"./ReactInstanceHandles":57,"./ReactMount":60,"./ReactMultiChild":62,"./ReactPerf":65,"./ReactPropTypes":69,"./ReactServerRendering":73,"./ReactTextComponent":77,"./onlyChild":141}],27:[function(_dereq_,module,exports){
+},{"./DOMPropertyOperations":12,"./EventPluginUtils":20,"./ExecutionEnvironment":22,"./ReactChildren":34,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDOM":41,"./ReactDOMComponent":43,"./ReactDefaultInjection":53,"./ReactDescriptor":56,"./ReactInstanceHandles":64,"./ReactMount":67,"./ReactMultiChild":68,"./ReactPerf":71,"./ReactPropTypes":75,"./ReactServerRendering":79,"./ReactTextComponent":83,"./onlyChild":149}],30:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3912,16 +4387,17 @@ module.exports = React;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactBrowserComponentMixin
  */
 
 "use strict";
 
+var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
 var ReactMount = _dereq_("./ReactMount");
 
 var invariant = _dereq_("./invariant");
 
 var ReactBrowserComponentMixin = {
   /**
    * Returns the DOM node rendered by this component.
    *
@@ -3929,23 +4405,388 @@ var ReactBrowserComponentMixin = {
    * @final
    * @protected
    */
   getDOMNode: function() {
     ("production" !== "development" ? invariant(
       this.isMounted(),
       'getDOMNode(): A component must be mounted to have a DOM node.'
     ) : invariant(this.isMounted()));
+    if (ReactEmptyComponent.isNullComponentID(this._rootNodeID)) {
+      return null;
+    }
     return ReactMount.getNode(this._rootNodeID);
   }
 };
 
 module.exports = ReactBrowserComponentMixin;
 
-},{"./ReactMount":60,"./invariant":125}],28:[function(_dereq_,module,exports){
+},{"./ReactEmptyComponent":58,"./ReactMount":67,"./invariant":134}],31:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ReactBrowserEventEmitter
+ * @typechecks static-only
+ */
+
+"use strict";
+
+var EventConstants = _dereq_("./EventConstants");
+var EventPluginHub = _dereq_("./EventPluginHub");
+var EventPluginRegistry = _dereq_("./EventPluginRegistry");
+var ReactEventEmitterMixin = _dereq_("./ReactEventEmitterMixin");
+var ViewportMetrics = _dereq_("./ViewportMetrics");
+
+var isEventSupported = _dereq_("./isEventSupported");
+var merge = _dereq_("./merge");
+
+/**
+ * Summary of `ReactBrowserEventEmitter` event handling:
+ *
+ *  - Top-level delegation is used to trap most native browser events. This
+ *    may only occur in the main thread and is the responsibility of
+ *    ReactEventListener, which is injected and can therefore support pluggable
+ *    event sources. This is the only work that occurs in the main thread.
+ *
+ *  - We normalize and de-duplicate events to account for browser quirks. This
+ *    may be done in the worker thread.
+ *
+ *  - Forward these native events (with the associated top-level type used to
+ *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want
+ *    to extract any synthetic events.
+ *
+ *  - The `EventPluginHub` will then process each event by annotating them with
+ *    "dispatches", a sequence of listeners and IDs that care about that event.
+ *
+ *  - The `EventPluginHub` then dispatches the events.
+ *
+ * Overview of React and the event system:
+ *
+ * +------------+    .
+ * |    DOM     |    .
+ * +------------+    .
+ *       |           .
+ *       v           .
+ * +------------+    .
+ * | ReactEvent |    .
+ * |  Listener  |    .
+ * +------------+    .                         +-----------+
+ *       |           .               +--------+|SimpleEvent|
+ *       |           .               |         |Plugin     |
+ * +-----|------+    .               v         +-----------+
+ * |     |      |    .    +--------------+                    +------------+
+ * |     +-----------.--->|EventPluginHub|                    |    Event   |
+ * |            |    .    |              |     +-----------+  | Propagators|
+ * | ReactEvent |    .    |              |     |TapEvent   |  |------------|
+ * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|
+ * |            |    .    |              |     +-----------+  |  utilities |
+ * |     +-----------.--->|              |                    +------------+
+ * |     |      |    .    +--------------+
+ * +-----|------+    .                ^        +-----------+
+ *       |           .                |        |Enter/Leave|
+ *       +           .                +-------+|Plugin     |
+ * +-------------+   .                         +-----------+
+ * | application |   .
+ * |-------------|   .
+ * |             |   .
+ * |             |   .
+ * +-------------+   .
+ *                   .
+ *    React Core     .  General Purpose Event Plugin System
+ */
+
+var alreadyListeningTo = {};
+var isMonitoringScrollValue = false;
+var reactTopListenersCounter = 0;
+
+// For events like 'submit' which don't consistently bubble (which we trap at a
+// lower node than `document`), binding at `document` would cause duplicate
+// events so we don't include them here
+var topEventMapping = {
+  topBlur: 'blur',
+  topChange: 'change',
+  topClick: 'click',
+  topCompositionEnd: 'compositionend',
+  topCompositionStart: 'compositionstart',
+  topCompositionUpdate: 'compositionupdate',
+  topContextMenu: 'contextmenu',
+  topCopy: 'copy',
+  topCut: 'cut',
+  topDoubleClick: 'dblclick',
+  topDrag: 'drag',
+  topDragEnd: 'dragend',
+  topDragEnter: 'dragenter',
+  topDragExit: 'dragexit',
+  topDragLeave: 'dragleave',
+  topDragOver: 'dragover',
+  topDragStart: 'dragstart',
+  topDrop: 'drop',
+  topFocus: 'focus',
+  topInput: 'input',
+  topKeyDown: 'keydown',
+  topKeyPress: 'keypress',
+  topKeyUp: 'keyup',
+  topMouseDown: 'mousedown',
+  topMouseMove: 'mousemove',
+  topMouseOut: 'mouseout',
+  topMouseOver: 'mouseover',
+  topMouseUp: 'mouseup',
+  topPaste: 'paste',
+  topScroll: 'scroll',
+  topSelectionChange: 'selectionchange',
+  topTextInput: 'textInput',
+  topTouchCancel: 'touchcancel',
+  topTouchEnd: 'touchend',
+  topTouchMove: 'touchmove',
+  topTouchStart: 'touchstart',
+  topWheel: 'wheel'
+};
+
+/**
+ * To ensure no conflicts with other potential React instances on the page
+ */
+var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2);
+
+function getListeningForDocument(mountAt) {
+  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
+  // directly.
+  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
+    mountAt[topListenersIDKey] = reactTopListenersCounter++;
+    alreadyListeningTo[mountAt[topListenersIDKey]] = {};
+  }
+  return alreadyListeningTo[mountAt[topListenersIDKey]];
+}
+
+/**
+ * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For
+ * example:
+ *
+ *   ReactBrowserEventEmitter.putListener('myID', 'onClick', myFunction);
+ *
+ * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
+ *
+ * @internal
+ */
+var ReactBrowserEventEmitter = merge(ReactEventEmitterMixin, {
+
+  /**
+   * Injectable event backend
+   */
+  ReactEventListener: null,
+
+  injection: {
+    /**
+     * @param {object} ReactEventListener
+     */
+    injectReactEventListener: function(ReactEventListener) {
+      ReactEventListener.setHandleTopLevel(
+        ReactBrowserEventEmitter.handleTopLevel
+      );
+      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;
+    }
+  },
+
+  /**
+   * Sets whether or not any created callbacks should be enabled.
+   *
+   * @param {boolean} enabled True if callbacks should be enabled.
+   */
+  setEnabled: function(enabled) {
+    if (ReactBrowserEventEmitter.ReactEventListener) {
+      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);
+    }
+  },
+
+  /**
+   * @return {boolean} True if callbacks are enabled.
+   */
+  isEnabled: function() {
+    return !!(
+      ReactBrowserEventEmitter.ReactEventListener &&
+      ReactBrowserEventEmitter.ReactEventListener.isEnabled()
+    );
+  },
+
+  /**
+   * We listen for bubbled touch events on the document object.
+   *
+   * Firefox v8.01 (and possibly others) exhibited strange behavior when
+   * mounting `onmousemove` events at some node that was not the document
+   * element. The symptoms were that if your mouse is not moving over something
+   * contained within that mount point (for example on the background) the
+   * top-level listeners for `onmousemove` won't be called. However, if you
+   * register the `mousemove` on the document object, then it will of course
+   * catch all `mousemove`s. This along with iOS quirks, justifies restricting
+   * top-level listeners to the document object only, at least for these
+   * movement types of events and possibly all events.
+   *
+   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
+   *
+   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
+   * they bubble to document.
+   *
+   * @param {string} registrationName Name of listener (e.g. `onClick`).
+   * @param {object} contentDocumentHandle Document which owns the container
+   */
+  listenTo: function(registrationName, contentDocumentHandle) {
+    var mountAt = contentDocumentHandle;
+    var isListening = getListeningForDocument(mountAt);
+    var dependencies = EventPluginRegistry.
+      registrationNameDependencies[registrationName];
+
+    var topLevelTypes = EventConstants.topLevelTypes;
+    for (var i = 0, l = dependencies.length; i < l; i++) {
+      var dependency = dependencies[i];
+      if (!(
+            isListening.hasOwnProperty(dependency) &&
+            isListening[dependency]
+          )) {
+        if (dependency === topLevelTypes.topWheel) {
+          if (isEventSupported('wheel')) {
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topWheel,
+              'wheel',
+              mountAt
+            );
+          } else if (isEventSupported('mousewheel')) {
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topWheel,
+              'mousewheel',
+              mountAt
+            );
+          } else {
+            // Firefox needs to capture a different mouse scroll event.
+            // @see http://www.quirksmode.org/dom/events/tests/scroll.html
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topWheel,
+              'DOMMouseScroll',
+              mountAt
+            );
+          }
+        } else if (dependency === topLevelTypes.topScroll) {
+
+          if (isEventSupported('scroll', true)) {
+            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
+              topLevelTypes.topScroll,
+              'scroll',
+              mountAt
+            );
+          } else {
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topScroll,
+              'scroll',
+              ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE
+            );
+          }
+        } else if (dependency === topLevelTypes.topFocus ||
+            dependency === topLevelTypes.topBlur) {
+
+          if (isEventSupported('focus', true)) {
+            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
+              topLevelTypes.topFocus,
+              'focus',
+              mountAt
+            );
+            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
+              topLevelTypes.topBlur,
+              'blur',
+              mountAt
+            );
+          } else if (isEventSupported('focusin')) {
+            // IE has `focusin` and `focusout` events which bubble.
+            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topFocus,
+              'focusin',
+              mountAt
+            );
+            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+              topLevelTypes.topBlur,
+              'focusout',
+              mountAt
+            );
+          }
+
+          // to make sure blur and focus event listeners are only attached once
+          isListening[topLevelTypes.topBlur] = true;
+          isListening[topLevelTypes.topFocus] = true;
+        } else if (topEventMapping.hasOwnProperty(dependency)) {
+          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+            dependency,
+            topEventMapping[dependency],
+            mountAt
+          );
+        }
+
+        isListening[dependency] = true;
+      }
+    }
+  },
+
+  trapBubbledEvent: function(topLevelType, handlerBaseName, handle) {
+    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
+      topLevelType,
+      handlerBaseName,
+      handle
+    );
+  },
+
+  trapCapturedEvent: function(topLevelType, handlerBaseName, handle) {
+    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
+      topLevelType,
+      handlerBaseName,
+      handle
+    );
+  },
+
+  /**
+   * Listens to window scroll and resize events. We cache scroll values so that
+   * application code can access them without triggering reflows.
+   *
+   * NOTE: Scroll events do not bubble.
+   *
+   * @see http://www.quirksmode.org/dom/events/scroll.html
+   */
+  ensureScrollValueMonitoring: function(){
+    if (!isMonitoringScrollValue) {
+      var refresh = ViewportMetrics.refreshScrollValues;
+      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);
+      isMonitoringScrollValue = true;
+    }
+  },
+
+  eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs,
+
+  registrationNameModules: EventPluginHub.registrationNameModules,
+
+  putListener: EventPluginHub.putListener,
+
+  getListener: EventPluginHub.getListener,
+
+  deleteListener: EventPluginHub.deleteListener,
+
+  deleteAllListeners: EventPluginHub.deleteAllListeners
+
+});
+
+module.exports = ReactBrowserEventEmitter;
+
+},{"./EventConstants":16,"./EventPluginHub":18,"./EventPluginRegistry":19,"./ReactEventEmitterMixin":60,"./ViewportMetrics":105,"./isEventSupported":135,"./merge":144}],32:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -3963,16 +4804,18 @@ module.exports = ReactBrowserComponentMi
 "use strict";
 
 var React = _dereq_("./React");
 
 var ReactTransitionGroup = _dereq_("./ReactTransitionGroup");
 var ReactCSSTransitionGroupChild = _dereq_("./ReactCSSTransitionGroupChild");
 
 var ReactCSSTransitionGroup = React.createClass({
+  displayName: 'ReactCSSTransitionGroup',
+
   propTypes: {
     transitionName: React.PropTypes.string.isRequired,
     transitionEnter: React.PropTypes.bool,
     transitionLeave: React.PropTypes.bool
   },
 
   getDefaultProps: function() {
     return {
@@ -4002,17 +4845,17 @@ var ReactCSSTransitionGroup = React.crea
         this.props.children
       )
     );
   }
 });
 
 module.exports = ReactCSSTransitionGroup;
 
-},{"./React":26,"./ReactCSSTransitionGroupChild":29,"./ReactTransitionGroup":80}],29:[function(_dereq_,module,exports){
+},{"./React":29,"./ReactCSSTransitionGroupChild":33,"./ReactTransitionGroup":86}],33:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -4053,16 +4896,18 @@ if ("production" !== "development") {
       'an animationend or transitionend event after timeout (' +
       NO_EVENT_TIMEOUT + 'ms). You should either disable this ' +
       'transition in JS or add a CSS animation/transition.'
     );
   };
 }
 
 var ReactCSSTransitionGroupChild = React.createClass({
+  displayName: 'ReactCSSTransitionGroupChild',
+
   transition: function(animationType, finishCallback) {
     var node = this.getDOMNode();
     var className = this.props.name + '-' + animationType;
     var activeClassName = className + '-active';
     var noEventTimeout = null;
 
     var endListener = function() {
       if ("production" !== "development") {
@@ -4089,21 +4934,16 @@ var ReactCSSTransitionGroupChild = React
     if ("production" !== "development") {
       noEventTimeout = setTimeout(noEventListener, NO_EVENT_TIMEOUT);
     }
   },
 
   queueClass: function(className) {
     this.classNameQueue.push(className);
 
-    if (this.props.runNextTick) {
-      this.props.runNextTick(this.flushClassNameQueue);
-      return;
-    }
-
     if (!this.timeout) {
       this.timeout = setTimeout(this.flushClassNameQueue, TICK);
     }
   },
 
   flushClassNameQueue: function() {
     if (this.isMounted()) {
       this.classNameQueue.forEach(
@@ -4142,17 +4982,17 @@ var ReactCSSTransitionGroupChild = React
 
   render: function() {
     return onlyChild(this.props.children);
   }
 });
 
 module.exports = ReactCSSTransitionGroupChild;
 
-},{"./CSSCore":2,"./React":26,"./ReactTransitionEvents":79,"./onlyChild":141}],30:[function(_dereq_,module,exports){
+},{"./CSSCore":3,"./React":29,"./ReactTransitionEvents":85,"./onlyChild":149}],34:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -4165,18 +5005,18 @@ module.exports = ReactCSSTransitionGroup
  *
  * @providesModule ReactChildren
  */
 
 "use strict";
 
 var PooledClass = _dereq_("./PooledClass");
 
-var invariant = _dereq_("./invariant");
 var traverseAllChildren = _dereq_("./traverseAllChildren");
+var warning = _dereq_("./warning");
 
 var twoArgumentPooler = PooledClass.twoArgumentPooler;
 var threeArgumentPooler = PooledClass.threeArgumentPooler;
 
 /**
  * PooledClass representing the bookkeeping associated with performing a child
  * traversal. Allows avoiding binding callbacks.
  *
@@ -4231,26 +5071,31 @@ function MapBookKeeping(mapResult, mapFu
   this.mapFunction = mapFunction;
   this.mapContext = mapContext;
 }
 PooledClass.addPoolingTo(MapBookKeeping, threeArgumentPooler);
 
 function mapSingleChildIntoContext(traverseContext, child, name, i) {
   var mapBookKeeping = traverseContext;
   var mapResult = mapBookKeeping.mapResult;
-  var mappedChild =
-    mapBookKeeping.mapFunction.call(mapBookKeeping.mapContext, child, i);
-  // We found a component instance
-  ("production" !== "development" ? invariant(
-    !mapResult.hasOwnProperty(name),
+
+  var keyUnique = !mapResult.hasOwnProperty(name);
+  ("production" !== "development" ? warning(
+    keyUnique,
     'ReactChildren.map(...): Encountered two children with the same key, ' +
-    '`%s`. Children keys must be unique.',
+    '`%s`. Child keys must be unique; when two children share a key, only ' +
+    'the first child will be used.',
     name
-  ) : invariant(!mapResult.hasOwnProperty(name)));
-  mapResult[name] = mappedChild;
+  ) : null);
+
+  if (keyUnique) {
+    var mappedChild =
+      mapBookKeeping.mapFunction.call(mapBookKeeping.mapContext, child, i);
+    mapResult[name] = mappedChild;
+  }
 }
 
 /**
  * Maps children that are typically specified as `props.children`.
  *
  * The provided mapFunction(child, key, index) will be called for each
  * leaf child.
  *
@@ -4269,24 +5114,40 @@ function mapChildren(children, func, con
 
   var mapResult = {};
   var traverseContext = MapBookKeeping.getPooled(mapResult, func, context);
   traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
   MapBookKeeping.release(traverseContext);
   return mapResult;
 }
 
+function forEachSingleChildDummy(traverseContext, child, name, i) {
+  return null;
+}
+
+/**
+ * Count the number of children that are typically specified as
+ * `props.children`.
+ *
+ * @param {?*} children Children tree container.
+ * @return {number} The number of children.
+ */
+function countChildren(children, context) {
+  return traverseAllChildren(children, forEachSingleChildDummy, null);
+}
+
 var ReactChildren = {
   forEach: forEachChildren,
-  map: mapChildren
+  map: mapChildren,
+  count: countChildren
 };
 
 module.exports = ReactChildren;
 
-},{"./PooledClass":25,"./invariant":125,"./traverseAllChildren":146}],31:[function(_dereq_,module,exports){
+},{"./PooledClass":28,"./traverseAllChildren":156,"./warning":158}],35:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -4297,52 +5158,39 @@ module.exports = ReactChildren;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactComponent
  */
 
 "use strict";
 
-var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+var ReactDescriptor = _dereq_("./ReactDescriptor");
 var ReactOwner = _dereq_("./ReactOwner");
 var ReactUpdates = _dereq_("./ReactUpdates");
 
 var invariant = _dereq_("./invariant");
 var keyMirror = _dereq_("./keyMirror");
 var merge = _dereq_("./merge");
-var monitorCodeUse = _dereq_("./monitorCodeUse");
 
 /**
  * Every React component is in one of these life cycles.
  */
 var ComponentLifeCycle = keyMirror({
   /**
    * Mounted components have a DOM node representation and are capable of
    * receiving new props.
    */
   MOUNTED: null,
   /**
    * Unmounted components are inactive and cannot receive new props.
    */
   UNMOUNTED: null
 });
 
-/**
- * Warn if there's no key explicitly set on dynamic arrays of children or
- * object keys are not valid. This allows us to keep track of children between
- * updates.
- */
-
-var ownerHasExplicitKeyWarning = {};
-var ownerHasPropertyWarning = {};
-var ownerHasMonitoredObjectMap = {};
-
-var NUMERIC_PROPERTY_REGEX = /^\d+$/;
-
 var injected = false;
 
 /**
  * Optionally injectable environment dependent cleanup hook. (server vs.
  * browser etc). Example: A browser system caches DOM nodes based on component
  * ID and must remove that cache entry when this instance is unmounted.
  *
  * @private
@@ -4356,140 +5204,16 @@ var unmountIDFromEnvironment = null;
  * low level `div` and `span` nodes. Other platforms may have different
  * encoding of this "image". This must be injected.
  *
  * @private
  */
 var mountImageIntoNode = null;
 
 /**
- * Warn if the component doesn't have an explicit key assigned to it.
- * This component is in an array. The array could grow and shrink or be
- * reordered. All children that haven't already been validated are required to
- * have a "key" property assigned to it.
- *
- * @internal
- * @param {ReactComponent} component Component that requires a key.
- */
-function validateExplicitKey(component) {
-  if (component.__keyValidated__ || component.props.key != null) {
-    return;
-  }
-  component.__keyValidated__ = true;
-
-  // We can't provide friendly warnings for top level components.
-  if (!ReactCurrentOwner.current) {
-    return;
-  }
-
-  // Name of the component whose render method tried to pass children.
-  var currentName = ReactCurrentOwner.current.constructor.displayName;
-  if (ownerHasExplicitKeyWarning.hasOwnProperty(currentName)) {
-    return;
-  }
-  ownerHasExplicitKeyWarning[currentName] = true;
-
-  var message = 'Each child in an array should have a unique "key" prop. ' +
-                'Check the render method of ' + currentName + '.';
-
-  var childOwnerName = null;
-  if (!component.isOwnedBy(ReactCurrentOwner.current)) {
-    // Name of the component that originally created this child.
-    childOwnerName =
-      component._owner &&
-      component._owner.constructor.displayName;
-
-    // Usually the current owner is the offender, but if it accepts
-    // children as a property, it may be the creator of the child that's
-    // responsible for assigning it a key.
-    message += ' It was passed a child from ' + childOwnerName + '.';
-  }
-
-  message += ' See http://fb.me/react-warning-keys for more information.';
-  monitorCodeUse('react_key_warning', {
-    component: currentName,
-    componentOwner: childOwnerName
-  });
-  console.warn(message);
-}
-
-/**
- * Warn if the key is being defined as an object property but has an incorrect
- * value.
- *
- * @internal
- * @param {string} name Property name of the key.
- * @param {ReactComponent} component Component that requires a key.
- */
-function validatePropertyKey(name) {
-  if (NUMERIC_PROPERTY_REGEX.test(name)) {
-    // Name of the component whose render method tried to pass children.
-    var currentName = ReactCurrentOwner.current.constructor.displayName;
-    if (ownerHasPropertyWarning.hasOwnProperty(currentName)) {
-      return;
-    }
-    ownerHasPropertyWarning[currentName] = true;
-
-    monitorCodeUse('react_numeric_key_warning');
-    console.warn(
-      'Child objects should have non-numeric keys so ordering is preserved. ' +
-      'Check the render method of ' + currentName + '. ' +
-      'See http://fb.me/react-warning-keys for more information.'
-    );
-  }
-}
-
-/**
- * Log that we're using an object map. We're considering deprecating this
- * feature and replace it with proper Map and ImmutableMap data structures.
- *
- * @internal
- */
-function monitorUseOfObjectMap() {
-  // Name of the component whose render method tried to pass children.
-  // We only use this to avoid spewing the logs. We lose additional
-  // owner stacks but hopefully one level is enough to trace the source.
-  var currentName = (ReactCurrentOwner.current &&
-                    ReactCurrentOwner.current.constructor.displayName) || '';
-  if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) {
-    return;
-  }
-  ownerHasMonitoredObjectMap[currentName] = true;
-  monitorCodeUse('react_object_map_children');
-}
-
-/**
- * Ensure that every component either is passed in a static location, in an
- * array with an explicit keys property defined, or in an object literal
- * with valid key property.
- *
- * @internal
- * @param {*} component Statically passed child of any type.
- * @return {boolean}
- */
-function validateChildKeys(component) {
-  if (Array.isArray(component)) {
-    for (var i = 0; i < component.length; i++) {
-      var child = component[i];
-      if (ReactComponent.isValidComponent(child)) {
-        validateExplicitKey(child);
-      }
-    }
-  } else if (ReactComponent.isValidComponent(component)) {
-    // This component was passed in a valid location.
-    component.__keyValidated__ = true;
-  } else if (component && typeof component === 'object') {
-    monitorUseOfObjectMap();
-    for (var name in component) {
-      validatePropertyKey(name, component);
-    }
-  }
-}
-
-/**
  * Components are the basic units of composition in React.
  *
  * Every component accepts a set of keyed input parameters known as "props" that
  * are initialized by the constructor. Once a component is mounted, the props
  * can be mutated using `setProps` or `replaceProps`.
  *
  * Every component is capable of the following operations:
  *
@@ -4517,65 +5241,35 @@ var ReactComponent = {
         !injected,
         'ReactComponent: injectEnvironment() can only be called once.'
       ) : invariant(!injected));
       mountImageIntoNode = ReactComponentEnvironment.mountImageIntoNode;
       unmountIDFromEnvironment =
         ReactComponentEnvironment.unmountIDFromEnvironment;
       ReactComponent.BackendIDOperations =
         ReactComponentEnvironment.BackendIDOperations;
-      ReactComponent.ReactReconcileTransaction =
-        ReactComponentEnvironment.ReactReconcileTransaction;
       injected = true;
     }
   },
 
   /**
-   * @param {?object} object
-   * @return {boolean} True if `object` is a valid component.
-   * @final
-   */
-  isValidComponent: function(object) {
-    if (!object || !object.type || !object.type.prototype) {
-      return false;
-    }
-    // This is the safer way of duck checking the type of instance this is.
-    // The object can be a generic descriptor but the type property refers to
-    // the constructor and it's prototype can be used to inspect the type that
-    // will actually get mounted.
-    var prototype = object.type.prototype;
-    return (
-      typeof prototype.mountComponentIntoNode === 'function' &&
-      typeof prototype.receiveComponent === 'function'
-    );
-  },
-
-  /**
    * @internal
    */
   LifeCycle: ComponentLifeCycle,
 
   /**
    * Injected module that provides ability to mutate individual properties.
    * Injected into the base class because many different subclasses need access
    * to this.
    *
    * @internal
    */
   BackendIDOperations: null,
 
   /**
-   * React references `ReactReconcileTransaction` using this property in order
-   * to allow dependency injection.
-   *
-   * @internal
-   */
-  ReactReconcileTransaction: null,
-
-  /**
    * Base functionality for every ReactComponent constructor. Mixed into the
    * `ReactComponent` prototype, but exposed statically for easy access.
    *
    * @lends {ReactComponent.prototype}
    */
   Mixin: {
 
     /**
@@ -4593,19 +5287,21 @@ var ReactComponent = {
      * Sets a subset of the props.
      *
      * @param {object} partialProps Subset of the next props.
      * @param {?function} callback Called after props are updated.
      * @final
      * @public
      */
     setProps: function(partialProps, callback) {
-      // Merge with `_pendingProps` if it exists, otherwise with existing props.
+      // Merge with the pending descriptor if it exists, otherwise with existing
+      // descriptor props.
+      var descriptor = this._pendingDescriptor || this._descriptor;
       this.replaceProps(
-        merge(this._pendingProps || this.props, partialProps),
+        merge(descriptor.props, partialProps),
         callback
       );
     },
 
     /**
      * Replaces all of the props.
      *
      * @param {object} props New props.
@@ -4621,63 +5317,74 @@ var ReactComponent = {
       ("production" !== "development" ? invariant(
         this._mountDepth === 0,
         'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
         'component with a parent. This is an anti-pattern since props will ' +
         'get reactively updated when rendered. Instead, change the owner\'s ' +
         '`render` method to pass the correct value as props to the component ' +
         'where it is created.'
       ) : invariant(this._mountDepth === 0));
-      this._pendingProps = props;
+      // This is a deoptimized path. We optimize for always having a descriptor.
+      // This creates an extra internal descriptor.
+      this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps(
+        this._pendingDescriptor || this._descriptor,
+        props
+      );
+      ReactUpdates.enqueueUpdate(this, callback);
+    },
+
+    /**
+     * Schedule a partial update to the props. Only used for internal testing.
+     *
+     * @param {object} partialProps Subset of the next props.
+     * @param {?function} callback Called after props are updated.
+     * @final
+     * @internal
+     */
+    _setPropsInternal: function(partialProps, callback) {
+      // This is a deoptimized path. We optimize for always having a descriptor.
+      // This creates an extra internal descriptor.
+      var descriptor = this._pendingDescriptor || this._descriptor;
+      this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps(
+        descriptor,
+        merge(descriptor.props, partialProps)
+      );
       ReactUpdates.enqueueUpdate(this, callback);
     },
 
     /**
      * Base constructor for all React components.
      *
      * Subclasses that override this method should make sure to invoke
      * `ReactComponent.Mixin.construct.call(this, ...)`.
      *
-     * @param {?object} initialProps
-     * @param {*} children
+     * @param {ReactDescriptor} descriptor
      * @internal
      */
-    construct: function(initialProps, children) {
-      this.props = initialProps || {};
+    construct: function(descriptor) {
+      // This is the public exposed props object after it has been processed
+      // with default props. The descriptor's props represents the true internal
+      // state of the props.
+      this.props = descriptor.props;
       // Record the component responsible for creating this component.
-      this._owner = ReactCurrentOwner.current;
+      // This is accessible through the descriptor but we maintain an extra
+      // field for compatibility with devtools and as a way to make an
+      // incremental update. TODO: Consider deprecating this field.
+      this._owner = descriptor._owner;
+
       // All components start unmounted.
       this._lifeCycleState = ComponentLifeCycle.UNMOUNTED;
 
-      this._pendingProps = null;
+      // See ReactUpdates.
       this._pendingCallbacks = null;
 
-      // Unlike _pendingProps and _pendingCallbacks, we won't use null to
-      // indicate that nothing is pending because it's possible for a component
-      // to have a null owner. Instead, an owner change is pending when
-      // this._owner !== this._pendingOwner.
-      this._pendingOwner = this._owner;
-
-      // Children can be more than one argument
-      var childrenLength = arguments.length - 1;
-      if (childrenLength === 1) {
-        if ("production" !== "development") {
-          validateChildKeys(children);
-        }
-        this.props.children = children;
-      } else if (childrenLength > 1) {
-        var childArray = Array(childrenLength);
-        for (var i = 0; i < childrenLength; i++) {
-          if ("production" !== "development") {
-            validateChildKeys(arguments[i + 1]);
-          }
-          childArray[i] = arguments[i + 1];
-        }
-        this.props.children = childArray;
-      }
+      // We keep the old descriptor and a reference to the pending descriptor
+      // to track updates.
+      this._descriptor = descriptor;
+      this._pendingDescriptor = null;
     },
 
     /**
      * Initializes the component, renders markup, and registers event listeners.
      *
      * NOTE: This does not insert any nodes into the DOM.
      *
      * Subclasses that override this method should make sure to invoke
@@ -4692,19 +5399,20 @@ var ReactComponent = {
     mountComponent: function(rootID, transaction, mountDepth) {
       ("production" !== "development" ? invariant(
         !this.isMounted(),
         'mountComponent(%s, ...): Can only mount an unmounted component. ' +
         'Make sure to avoid storing components between renders or reusing a ' +
         'single component instance in multiple places.',
         rootID
       ) : invariant(!this.isMounted()));
-      var props = this.props;
+      var props = this._descriptor.props;
       if (props.ref != null) {
-        ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
+        var owner = this._descriptor._owner;
+        ReactOwner.addComponentAsRefTo(this, props.ref, owner);
       }
       this._rootNodeID = rootID;
       this._lifeCycleState = ComponentLifeCycle.MOUNTED;
       this._mountDepth = mountDepth;
       // Effectively: return '';
     },
 
     /**
@@ -4737,101 +5445,105 @@ var ReactComponent = {
      *
      * Subclasses that override this method should make sure to invoke
      * `ReactComponent.Mixin.receiveComponent.call(this, ...)`.
      *
      * @param {object} nextComponent Next set of properties.
      * @param {ReactReconcileTransaction} transaction
      * @internal
      */
-    receiveComponent: function(nextComponent, transaction) {
+    receiveComponent: function(nextDescriptor, transaction) {
       ("production" !== "development" ? invariant(
         this.isMounted(),
         'receiveComponent(...): Can only update a mounted component.'
       ) : invariant(this.isMounted()));
-      this._pendingOwner = nextComponent._owner;
-      this._pendingProps = nextComponent.props;
-      this._performUpdateIfNecessary(transaction);
+      this._pendingDescriptor = nextDescriptor;
+      this.performUpdateIfNecessary(transaction);
     },
 
     /**
-     * Call `_performUpdateIfNecessary` within a new transaction.
-     *
-     * @internal
-     */
-    performUpdateIfNecessary: function() {
-      var transaction = ReactComponent.ReactReconcileTransaction.getPooled();
-      transaction.perform(this._performUpdateIfNecessary, this, transaction);
-      ReactComponent.ReactReconcileTransaction.release(transaction);
-    },
-
-    /**
-     * If `_pendingProps` is set, update the component.
+     * If `_pendingDescriptor` is set, update the component.
      *
      * @param {ReactReconcileTransaction} transaction
      * @internal
      */
-    _performUpdateIfNecessary: function(transaction) {
-      if (this._pendingProps == null) {
+    performUpdateIfNecessary: function(transaction) {
+      if (this._pendingDescriptor == null) {
         return;
       }
-      var prevProps = this.props;
-      var prevOwner = this._owner;
-      this.props = this._pendingProps;
-      this._owner = this._pendingOwner;
-      this._pendingProps = null;
-      this.updateComponent(transaction, prevProps, prevOwner);
+      var prevDescriptor = this._descriptor;
+      var nextDescriptor = this._pendingDescriptor;
+      this._descriptor = nextDescriptor;
+      this.props = nextDescriptor.props;
+      this._owner = nextDescriptor._owner;
+      this._pendingDescriptor = null;
+      this.updateComponent(transaction, prevDescriptor);
     },
 
     /**
      * Updates the component's currently mounted representation.
      *
      * @param {ReactReconcileTransaction} transaction
-     * @param {object} prevProps
+     * @param {object} prevDescriptor
      * @internal
      */
-    updateComponent: function(transaction, prevProps, prevOwner) {
-      var props = this.props;
+    updateComponent: function(transaction, prevDescriptor) {
+      var nextDescriptor = this._descriptor;
+
       // If either the owner or a `ref` has changed, make sure the newest owner
       // has stored a reference to `this`, and the previous owner (if different)
-      // has forgotten the reference to `this`.
-      if (this._owner !== prevOwner || props.ref !== prevProps.ref) {
-        if (prevProps.ref != null) {
+      // has forgotten the reference to `this`. We use the descriptor instead
+      // of the public this.props because the post processing cannot determine
+      // a ref. The ref conceptually lives on the descriptor.
+
+      // TODO: Should this even be possible? The owner cannot change because
+      // it's forbidden by shouldUpdateReactComponent. The ref can change
+      // if you swap the keys of but not the refs. Reconsider where this check
+      // is made. It probably belongs where the key checking and
+      // instantiateReactComponent is done.
+
+      if (nextDescriptor._owner !== prevDescriptor._owner ||
+          nextDescriptor.props.ref !== prevDescriptor.props.ref) {
+        if (prevDescriptor.props.ref != null) {
           ReactOwner.removeComponentAsRefFrom(
-            this, prevProps.ref, prevOwner
+            this, prevDescriptor.props.ref, prevDescriptor._owner
           );
         }
         // Correct, even if the owner is the same, and only the ref has changed.
-        if (props.ref != null) {
-          ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
+        if (nextDescriptor.props.ref != null) {
+          ReactOwner.addComponentAsRefTo(
+            this,
+            nextDescriptor.props.ref,
+            nextDescriptor._owner
+          );
         }
       }
     },
 
     /**
      * Mounts this component and inserts it into the DOM.
      *
      * @param {string} rootID DOM ID of the root node.
      * @param {DOMElement} container DOM element to mount into.
      * @param {boolean} shouldReuseMarkup If true, do not insert markup
      * @final
      * @internal
      * @see {ReactMount.renderComponent}
      */
     mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) {
-      var transaction = ReactComponent.ReactReconcileTransaction.getPooled();
+      var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
       transaction.perform(
         this._mountComponentIntoNode,
         this,
         rootID,
         container,
         transaction,
         shouldReuseMarkup
       );
-      ReactComponent.ReactReconcileTransaction.release(transaction);
+      ReactUpdates.ReactReconcileTransaction.release(transaction);
     },
 
     /**
      * @param {string} rootID DOM ID of the root node.
      * @param {DOMElement} container DOM element to mount into.
      * @param {ReactReconcileTransaction} transaction
      * @param {boolean} shouldReuseMarkup If true, do not insert markup
      * @final
@@ -4873,17 +5585,17 @@ var ReactComponent = {
       }
       return owner.refs[ref];
     }
   }
 };
 
 module.exports = ReactComponent;
 
-},{"./ReactCurrentOwner":35,"./ReactOwner":64,"./ReactUpdates":81,"./invariant":125,"./keyMirror":131,"./merge":134,"./monitorCodeUse":138}],32:[function(_dereq_,module,exports){
+},{"./ReactDescriptor":56,"./ReactOwner":70,"./ReactUpdates":87,"./invariant":134,"./keyMirror":140,"./merge":144}],36:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -4904,16 +5616,17 @@ module.exports = ReactComponent;
 var ReactDOMIDOperations = _dereq_("./ReactDOMIDOperations");
 var ReactMarkupChecksum = _dereq_("./ReactMarkupChecksum");
 var ReactMount = _dereq_("./ReactMount");
 var ReactPerf = _dereq_("./ReactPerf");
 var ReactReconcileTransaction = _dereq_("./ReactReconcileTransaction");
 
 var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer");
 var invariant = _dereq_("./invariant");
+var setInnerHTML = _dereq_("./setInnerHTML");
 
 
 var ELEMENT_NODE_TYPE = 1;
 var DOC_NODE_TYPE = 9;
 
 
 /**
  * Abstracts away all functionality of `ReactComponent` requires knowledge of
@@ -4974,17 +5687,17 @@ var ReactComponentBrowserEnvironment = {
             'and ensure the props are the same client and server side.'
           ) : invariant(container.nodeType !== DOC_NODE_TYPE));
 
           if ("production" !== "development") {
             console.warn(
               'React attempted to use reuse markup in a container but the ' +
               'checksum was invalid. This generally means that you are ' +
               'using server rendering and the markup generated on the ' +
-              'server was not what the client was expecting. React injected' +
+              'server was not what the client was expecting. React injected ' +
               'new markup to compensate which works but you have lost many ' +
               'of the benefits of server rendering. Instead, figure out ' +
               'why the markup being generated is different on the client ' +
               'or server.'
             );
           }
         }
       }
@@ -4992,24 +5705,80 @@ var ReactComponentBrowserEnvironment = {
       ("production" !== "development" ? invariant(
         container.nodeType !== DOC_NODE_TYPE,
         'You\'re trying to render a component to the document but ' +
           'you didn\'t use server rendering. We can\'t do this ' +
           'without using server rendering due to cross-browser quirks. ' +
           'See renderComponentToString() for server rendering.'
       ) : invariant(container.nodeType !== DOC_NODE_TYPE));
 
-      container.innerHTML = markup;
+      setInnerHTML(container, markup);
     }
   )
 };
 
 module.exports = ReactComponentBrowserEnvironment;
 
-},{"./ReactDOMIDOperations":40,"./ReactMarkupChecksum":59,"./ReactMount":60,"./ReactPerf":65,"./ReactReconcileTransaction":71,"./getReactRootElementInContainer":120,"./invariant":125}],33:[function(_dereq_,module,exports){
+},{"./ReactDOMIDOperations":45,"./ReactMarkupChecksum":66,"./ReactMount":67,"./ReactPerf":71,"./ReactReconcileTransaction":77,"./getReactRootElementInContainer":128,"./invariant":134,"./setInnerHTML":152}],37:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+* @providesModule ReactComponentWithPureRenderMixin
+*/
+
+"use strict";
+
+var shallowEqual = _dereq_("./shallowEqual");
+
+/**
+ * If your React component's render function is "pure", e.g. it will render the
+ * same result given the same props and state, provide this Mixin for a
+ * considerable performance boost.
+ *
+ * Most React components have pure render functions.
+ *
+ * Example:
+ *
+ *   var ReactComponentWithPureRenderMixin =
+ *     require('ReactComponentWithPureRenderMixin');
+ *   React.createClass({
+ *     mixins: [ReactComponentWithPureRenderMixin],
+ *
+ *     render: function() {
+ *       return <div className={this.props.className}>foo</div>;
+ *     }
+ *   });
+ *
+ * Note: This only checks shallow equality for props and state. If these contain
+ * complex data structures this mixin may have false-negatives for deeper
+ * differences. Only mixin to components which have simple props and state, or
+ * use `forceUpdate()` when you know deep data structures have changed.
+ */
+var ReactComponentWithPureRenderMixin = {
+  shouldComponentUpdate: function(nextProps, nextState) {
+    return !shallowEqual(this.props, nextProps) ||
+           !shallowEqual(this.state, nextState);
+  }
+};
+
+module.exports = ReactComponentWithPureRenderMixin;
+
+},{"./shallowEqual":153}],38:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -5023,31 +5792,34 @@ module.exports = ReactComponentBrowserEn
  * @providesModule ReactCompositeComponent
  */
 
 "use strict";
 
 var ReactComponent = _dereq_("./ReactComponent");
 var ReactContext = _dereq_("./ReactContext");
 var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+var ReactDescriptor = _dereq_("./ReactDescriptor");
+var ReactDescriptorValidator = _dereq_("./ReactDescriptorValidator");
+var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
 var ReactErrorUtils = _dereq_("./ReactErrorUtils");
 var ReactOwner = _dereq_("./ReactOwner");
 var ReactPerf = _dereq_("./ReactPerf");
 var ReactPropTransferer = _dereq_("./ReactPropTransferer");
 var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations");
 var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames");
 var ReactUpdates = _dereq_("./ReactUpdates");
 
 var instantiateReactComponent = _dereq_("./instantiateReactComponent");
 var invariant = _dereq_("./invariant");
 var keyMirror = _dereq_("./keyMirror");
 var merge = _dereq_("./merge");
 var mixInto = _dereq_("./mixInto");
 var monitorCodeUse = _dereq_("./monitorCodeUse");
-var objMap = _dereq_("./objMap");
+var mapObject = _dereq_("./mapObject");
 var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent");
 var warning = _dereq_("./warning");
 
 /**
  * Policies that describe methods in `ReactCompositeComponentInterface`.
  */
 var SpecPolicy = keyMirror({
   /**
@@ -5328,60 +6100,80 @@ var ReactCompositeComponentInterface = {
  *
  * Although these are declared like instance properties in the specification
  * when defining classes using `React.createClass`, they are actually static
  * and are accessible on the constructor instead of the prototype. Despite
  * being static, they must be defined outside of the "statics" key under
  * which all other static methods are defined.
  */
 var RESERVED_SPEC_KEYS = {
-  displayName: function(ConvenienceConstructor, displayName) {
-    ConvenienceConstructor.componentConstructor.displayName = displayName;
-  },
-  mixins: function(ConvenienceConstructor, mixins) {
+  displayName: function(Constructor, displayName) {
+    Constructor.displayName = displayName;
+  },
+  mixins: function(Constructor, mixins) {
     if (mixins) {
       for (var i = 0; i < mixins.length; i++) {
-        mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
-      }
-    }
-  },
-  childContextTypes: function(ConvenienceConstructor, childContextTypes) {
-    var Constructor = ConvenienceConstructor.componentConstructor;
+        mixSpecIntoComponent(Constructor, mixins[i]);
+      }
+    }
+  },
+  childContextTypes: function(Constructor, childContextTypes) {
     validateTypeDef(
       Constructor,
       childContextTypes,
       ReactPropTypeLocations.childContext
     );
     Constructor.childContextTypes = merge(
       Constructor.childContextTypes,
       childContextTypes
     );
   },
-  contextTypes: function(ConvenienceConstructor, contextTypes) {
-    var Constructor = ConvenienceConstructor.componentConstructor;
+  contextTypes: function(Constructor, contextTypes) {
     validateTypeDef(
       Constructor,
       contextTypes,
       ReactPropTypeLocations.context
     );
     Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
   },
-  propTypes: function(ConvenienceConstructor, propTypes) {
-    var Constructor = ConvenienceConstructor.componentConstructor;
+  /**
+   * Special case getDefaultProps which should move into statics but requires
+   * automatic merging.
+   */
+  getDefaultProps: function(Constructor, getDefaultProps) {
+    if (Constructor.getDefaultProps) {
+      Constructor.getDefaultProps = createMergedResultFunction(
+        Constructor.getDefaultProps,
+        getDefaultProps
+      );
+    } else {
+      Constructor.getDefaultProps = getDefaultProps;
+    }
+  },
+  propTypes: function(Constructor, propTypes) {
     validateTypeDef(
       Constructor,
       propTypes,
       ReactPropTypeLocations.prop
     );
     Constructor.propTypes = merge(Constructor.propTypes, propTypes);
   },
-  statics: function(ConvenienceConstructor, statics) {
-    mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
-  }
-};
+  statics: function(Constructor, statics) {
+    mixStaticSpecIntoComponent(Constructor, statics);
+  }
+};
+
+function getDeclarationErrorAddendum(component) {
+  var owner = component._owner || null;
+  if (owner && owner.constructor && owner.constructor.displayName) {
+    return ' Check the render method of `' + owner.constructor.displayName +
+      '`.';
+  }
+  return '';
+}
 
 function validateTypeDef(Constructor, typeDef, location) {
   for (var propName in typeDef) {
     if (typeDef.hasOwnProperty(propName)) {
       ("production" !== "development" ? invariant(
         typeof typeDef[propName] == 'function',
         '%s: %s type `%s` is invalid; it must be a function, usually from ' +
         'React.PropTypes.',
@@ -5389,17 +6181,19 @@ function validateTypeDef(Constructor, ty
         ReactPropTypeLocationNames[location],
         propName
       ) : invariant(typeof typeDef[propName] == 'function'));
     }
   }
 }
 
 function validateMethodOverride(proto, name) {
-  var specPolicy = ReactCompositeComponentInterface[name];
+  var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
+    ReactCompositeComponentInterface[name] :
+    null;
 
   // Disallow overriding of base class methods unless explicitly allowed.
   if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
     ("production" !== "development" ? invariant(
       specPolicy === SpecPolicy.OVERRIDE_BASE,
       'ReactCompositeComponentInterface: You are attempting to override ' +
       '`%s` from your class specification. Ensure that your method names ' +
       'do not overlap with React methods.',
@@ -5439,124 +6233,146 @@ function validateLifeCycleOnReplaceState
     'usually means you called setState() on an unmounted component.'
   ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
 }
 
 /**
  * Custom version of `mixInto` which handles policy validation and reserved
  * specification keys when building `ReactCompositeComponent` classses.
  */
-function mixSpecIntoComponent(ConvenienceConstructor, spec) {
+function mixSpecIntoComponent(Constructor, spec) {
   ("production" !== "development" ? invariant(
-    !isValidClass(spec),
+    !ReactDescriptor.isValidFactory(spec),
     'ReactCompositeComponent: You\'re attempting to ' +
     'use a component class as a mixin. Instead, just use a regular object.'
-  ) : invariant(!isValidClass(spec)));
+  ) : invariant(!ReactDescriptor.isValidFactory(spec)));
   ("production" !== "development" ? invariant(
-    !ReactComponent.isValidComponent(spec),
+    !ReactDescriptor.isValidDescriptor(spec),
     'ReactCompositeComponent: You\'re attempting to ' +
     'use a component as a mixin. Instead, just use a regular object.'
-  ) : invariant(!ReactComponent.isValidComponent(spec)));
-
-  var Constructor = ConvenienceConstructor.componentConstructor;
+  ) : invariant(!ReactDescriptor.isValidDescriptor(spec)));
+
   var proto = Constructor.prototype;
   for (var name in spec) {
     var property = spec[name];
     if (!spec.hasOwnProperty(name)) {
       continue;
     }
 
     validateMethodOverride(proto, name);
 
     if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
-      RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
+      RESERVED_SPEC_KEYS[name](Constructor, property);
     } else {
       // Setup methods on prototype:
       // The following member methods should not be automatically bound:
       // 1. Expected ReactCompositeComponent methods (in the "interface").
       // 2. Overridden methods (that were mixed in).
-      var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
-      var isInherited = name in proto;
+      var isCompositeComponentMethod =
+        ReactCompositeComponentInterface.hasOwnProperty(name);
+      var isAlreadyDefined = proto.hasOwnProperty(name);
       var markedDontBind = property && property.__reactDontBind;
       var isFunction = typeof property === 'function';
       var shouldAutoBind =
         isFunction &&
         !isCompositeComponentMethod &&
-        !isInherited &&
+        !isAlreadyDefined &&
         !markedDontBind;
 
       if (shouldAutoBind) {
         if (!proto.__reactAutoBindMap) {
           proto.__reactAutoBindMap = {};
         }
         proto.__reactAutoBindMap[name] = property;
         proto[name] = property;
       } else {
-        if (isInherited) {
+        if (isAlreadyDefined) {
+          var specPolicy = ReactCompositeComponentInterface[name];
+
+          // These cases should already be caught by validateMethodOverride
+          ("production" !== "development" ? invariant(
+            isCompositeComponentMethod && (
+              specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
+              specPolicy === SpecPolicy.DEFINE_MANY
+            ),
+            'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
+            'when mixing in component specs.',
+            specPolicy,
+            name
+          ) : invariant(isCompositeComponentMethod && (
+            specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
+            specPolicy === SpecPolicy.DEFINE_MANY
+          )));
+
           // For methods which are defined more than once, call the existing
-          // methods before calling the new property.
-          if (ReactCompositeComponentInterface[name] ===
-              SpecPolicy.DEFINE_MANY_MERGED) {
+          // methods before calling the new property, merging if appropriate.
+          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
             proto[name] = createMergedResultFunction(proto[name], property);
-          } else {
+          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {
             proto[name] = createChainedFunction(proto[name], property);
           }
         } else {
           proto[name] = property;
-        }
-      }
-    }
-  }
-}
-
-function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
+          if ("production" !== "development") {
+            // Add verbose displayName to the function, which helps when looking
+            // at profiling tools.
+            if (typeof property === 'function' && spec.displayName) {
+              proto[name].displayName = spec.displayName + '_' + name;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+function mixStaticSpecIntoComponent(Constructor, statics) {
   if (!statics) {
     return;
   }
   for (var name in statics) {
     var property = statics[name];
     if (!statics.hasOwnProperty(name)) {
-      return;
-    }
-
-    var isInherited = name in ConvenienceConstructor;
+      continue;
+    }
+
+    var isInherited = name in Constructor;
     var result = property;
     if (isInherited) {
-      var existingProperty = ConvenienceConstructor[name];
+      var existingProperty = Constructor[name];
       var existingType = typeof existingProperty;
       var propertyType = typeof property;
       ("production" !== "development" ? invariant(
         existingType === 'function' && propertyType === 'function',
         'ReactCompositeComponent: You are attempting to define ' +
         '`%s` on your component more than once, but that is only supported ' +
         'for functions, which are chained together. This conflict may be ' +
         'due to a mixin.',
         name
       ) : invariant(existingType === 'function' && propertyType === 'function'));
       result = createChainedFunction(existingProperty, property);
     }
-    ConvenienceConstructor[name] = result;
-    ConvenienceConstructor.componentConstructor[name] = result;
+    Constructor[name] = result;
   }
 }
 
 /**
  * Merge two objects, but throw if both contain the same key.
  *
  * @param {object} one The first object, which is mutated.
  * @param {object} two The second object
  * @return {object} one after it has been mutated to contain everything in two.
  */
 function mergeObjectsWithNoDuplicateKeys(one, two) {
   ("production" !== "development" ? invariant(
     one && two && typeof one === 'object' && typeof two === 'object',
     'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
   ) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
 
-  objMap(two, function(value, key) {
+  mapObject(two, function(value, key) {
     ("production" !== "development" ? invariant(
       one[key] === undefined,
       'mergeObjectsWithNoDuplicateKeys(): ' +
       'Tried to merge two objects with the same key: %s',
       key
     ) : invariant(one[key] === undefined));
     one[key] = value;
   });
@@ -5594,213 +6410,16 @@ function createMergedResultFunction(one,
  */
 function createChainedFunction(one, two) {
   return function chainedFunction() {
     one.apply(this, arguments);
     two.apply(this, arguments);
   };
 }
 
-if ("production" !== "development") {
-
-  var unmountedPropertyWhitelist = {
-    constructor: true,
-    construct: true,
-    isOwnedBy: true, // should be deprecated but can have code mod (internal)
-    type: true,
-    props: true,
-    // currently private but belong on the descriptor and are valid for use
-    // inside the framework:
-    __keyValidated__: true,
-    _owner: true,
-    _currentContext: true
-  };
-
-  var componentInstanceProperties = {
-    __keyValidated__: true,
-    __keySetters: true,
-    _compositeLifeCycleState: true,
-    _currentContext: true,
-    _defaultProps: true,
-    _instance: true,
-    _lifeCycleState: true,
-    _mountDepth: true,
-    _owner: true,
-    _pendingCallbacks: true,
-    _pendingContext: true,
-    _pendingForceUpdate: true,
-    _pendingOwner: true,
-    _pendingProps: true,
-    _pendingState: true,
-    _renderedComponent: true,
-    _rootNodeID: true,
-    context: true,
-    props: true,
-    refs: true,
-    state: true,
-
-    // These are known instance properties coming from other sources
-    _pendingQueries: true,
-    _queryPropListeners: true,
-    queryParams: true
-
-  };
-
-  var hasWarnedOnComponentType = {};
-
-  var warningStackCounter = 0;
-
-  var issueMembraneWarning = function(instance, key) {
-    var isWhitelisted = unmountedPropertyWhitelist.hasOwnProperty(key);
-    if (warningStackCounter > 0 || isWhitelisted) {
-      return;
-    }
-    var name = instance.constructor.displayName || 'Unknown';
-    var owner = ReactCurrentOwner.current;
-    var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
-    var warningKey = key + '|' + name + '|' + ownerName;
-    if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
-      // We have already warned for this combination. Skip it this time.
-      return;
-    }
-    hasWarnedOnComponentType[warningKey] = true;
-
-    var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
-    var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
-
-    monitorCodeUse('react_descriptor_property_access', { component: name });
-    console.warn(
-      'Invalid access to component property "' + key + '" on ' + name +
-      context + ' See http://fb.me/react-warning-descriptors .' +
-      ' Use a static method instead: ' + staticMethodExample
-    );
-  };
-
-  var wrapInMembraneFunction = function(fn, thisBinding) {
-    if (fn.__reactMembraneFunction && fn.__reactMembraneSelf === thisBinding) {
-      return fn.__reactMembraneFunction;
-    }
-    return fn.__reactMembraneFunction = function() {
-      /**
-       * By getting this function, you've already received a warning. The
-       * internals of this function will likely cause more warnings. To avoid
-       * Spamming too much we disable any warning triggered inside of this
-       * stack.
-       */
-      warningStackCounter++;
-      try {
-        // If the this binding is unchanged, we defer to the real component.
-        // This is important to keep some referential integrity in the
-        // internals. E.g. owner equality check.
-        var self = this === thisBinding ? this.__realComponentInstance : this;
-        return fn.apply(self, arguments);
-      } finally {
-        warningStackCounter--;
-      }
-    };
-  };
-
-  var defineMembraneProperty = function(membrane, prototype, key) {
-    Object.defineProperty(membrane, key, {
-
-      configurable: false,
-      enumerable: true,
-
-      get: function() {
-        if (this === membrane) {
-          // We're allowed to access the prototype directly.
-          return prototype[key];
-        }
-        issueMembraneWarning(this, key);
-
-        var realValue = this.__realComponentInstance[key];
-        // If the real value is a function, we need to provide a wrapper that
-        // disables nested warnings. The properties type and constructors are
-        // expected to the be constructors and therefore is often use with an
-        // equality check and we shouldn't try to rebind those.
-        if (typeof realValue === 'function' &&
-            key !== 'type' &&
-            key !== 'constructor') {
-          return wrapInMembraneFunction(realValue, this);
-        }
-        return realValue;
-      },
-
-      set: function(value) {
-        if (this === membrane) {
-          // We're allowed to set a value on the prototype directly.
-          prototype[key] = value;
-          return;
-        }
-        issueMembraneWarning(this, key);
-        this.__realComponentInstance[key] = value;
-      }
-
-    });
-  };
-
-  /**
-   * Creates a membrane prototype which wraps the original prototype. If any
-   * property is accessed in an unmounted state, a warning is issued.
-   *
-   * @param {object} prototype Original prototype.
-   * @return {object} The membrane prototype.
-   * @private
-   */
-  var createMountWarningMembrane = function(prototype) {
-    var membrane = {};
-    var key;
-    for (key in prototype) {
-      defineMembraneProperty(membrane, prototype, key);
-    }
-    // These are properties that goes into the instance but not the prototype.
-    // We can create the membrane on the prototype even though this will
-    // result in a faulty hasOwnProperty check it's better perf.
-    for (key in componentInstanceProperties) {
-      if (componentInstanceProperties.hasOwnProperty(key) &&
-          !(key in prototype)) {
-        defineMembraneProperty(membrane, prototype, key);
-      }
-    }
-    return membrane;
-  };
-
-  /**
-   * Creates a membrane constructor which wraps the component that gets mounted.
-   *
-   * @param {function} constructor Original constructor.
-   * @return {function} The membrane constructor.
-   * @private
-   */
-  var createDescriptorProxy = function(constructor) {
-    try {
-      var ProxyConstructor = function() {
-        this.__realComponentInstance = new constructor();
-
-        // We can only safely pass through known instance variables. Unknown
-        // expandos are not safe. Use the real mounted instance to avoid this
-        // problem if it blows something up.
-        Object.freeze(this);
-      };
-
-      ProxyConstructor.prototype = createMountWarningMembrane(
-        constructor.prototype
-      );
-
-      return ProxyConstructor;
-    } catch(x) {
-      // In IE8 define property will fail on non-DOM objects. If anything in
-      // the membrane creation fails, we'll bail out and just use the plain
-      // constructor without warnings.
-      return constructor;
-    }
-  };
-
-}
-
 /**
  * `ReactCompositeComponent` maintains an auxiliary life cycle state in
  * `this._compositeLifeCycleState` (which can be null).
  *
  * This is different from the life cycle state maintained by `ReactComponent` in
  * `this._lifeCycleState`. The following diagram shows how the states overlap in
  * time. There are times when the CompositeLifeCycle is null - at those times it
  * is only meaningful to look at ComponentLifeCycle alone.
@@ -5848,53 +6467,36 @@ var CompositeLifeCycle = keyMirror({
 /**
  * @lends {ReactCompositeComponent.prototype}
  */
 var ReactCompositeComponentMixin = {
 
   /**
    * Base constructor for all composite component.
    *
-   * @param {?object} initialProps
-   * @param {*} children
+   * @param {ReactDescriptor} descriptor
    * @final
    * @internal
    */
-  construct: function(initialProps, children) {
+  construct: function(descriptor) {
     // Children can be either an array or more than one argument
     ReactComponent.Mixin.construct.apply(this, arguments);
     ReactOwner.Mixin.construct.apply(this, arguments);
 
     this.state = null;
     this._pendingState = null;
 
+    // This is the public post-processed context. The real context and pending
+    // context lives on the descriptor.
     this.context = null;
-    this._currentContext = ReactContext.current;
-    this._pendingContext = null;
-
-    // The descriptor that was used to instantiate this component. Will be
-    // set by the instantiator instead of the constructor since this
-    // constructor is currently used by both instances and descriptors.
-    this._descriptor = null;
 
     this._compositeLifeCycleState = null;
   },
 
   /**
-   * Components in the intermediate state now has cyclic references. To avoid
-   * breaking JSON serialization we expose a custom JSON format.
-   * @return {object} JSON compatible representation.
-   * @internal
-   * @final
-   */
-  toJSON: function() {
-    return { type: this.type, props: this.props };
-  },
-
-  /**
    * Checks whether or not this composite component is mounted.
    * @return {boolean} True if mounted, false otherwise.
    * @protected
    * @final
    */
   isMounted: function() {
     return ReactComponent.Mixin.isMounted.call(this) &&
       this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
@@ -5917,24 +6519,23 @@ var ReactCompositeComponentMixin = {
       ReactComponent.Mixin.mountComponent.call(
         this,
         rootID,
         transaction,
         mountDepth
       );
       this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
 
-      this.context = this._processContext(this._currentContext);
-      this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
-      this.props = this._processProps(this.props);
-
       if (this.__reactAutoBindMap) {
         this._bindAutoBindMethods();
       }
 
+      this.context = this._processContext(this._descriptor._context);
+      this.props = this._processProps(this.props);
+
       this.state = this.getInitialState ? this.getInitialState() : null;
       ("production" !== "development" ? invariant(
         typeof this.state === 'object' && !Array.isArray(this.state),
         '%s.getInitialState(): must return an object or null',
         this.constructor.displayName || 'ReactCompositeComponent'
       ) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
 
       this._pendingState = null;
@@ -5957,17 +6558,17 @@ var ReactCompositeComponentMixin = {
       // Done with mounting, `setState` will now trigger UI changes.
       this._compositeLifeCycleState = null;
       var markup = this._renderedComponent.mountComponent(
         rootID,
         transaction,
         mountDepth + 1
       );
       if (this.componentDidMount) {
-        transaction.getReactMountReady().enqueue(this, this.componentDidMount);
+        transaction.getReactMountReady().enqueue(this.componentDidMount, this);
       }
       return markup;
     }
   ),
 
   /**
    * Releases any resources allocated by `mountComponent`.
    *
@@ -5976,18 +6577,16 @@ var ReactCompositeComponentMixin = {
    */
   unmountComponent: function() {
     this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
     if (this.componentWillUnmount) {
       this.componentWillUnmount();
     }
     this._compositeLifeCycleState = null;
 
-    this._defaultProps = null;
-
     this._renderedComponent.unmountComponent();
     this._renderedComponent = null;
 
     ReactComponent.Mixin.unmountComponent.call(this);
 
     // Some existing components rely on this.props even after they've been
     // destroyed (in event handlers).
     // TODO: this.props = null;
@@ -6011,17 +6610,17 @@ var ReactCompositeComponentMixin = {
    * @final
    * @protected
    */
   setState: function(partialState, callback) {
     ("production" !== "development" ? invariant(
       typeof partialState === 'object' || partialState == null,
       'setState(...): takes an object of state variables to update.'
     ) : invariant(typeof partialState === 'object' || partialState == null));
-    if ("production" !== "development") {
+    if ("production" !== "development"){
       ("production" !== "development" ? warning(
         partialState != null,
         'setState(...): You passed an undefined or null state object; ' +
         'instead, use forceUpdate().'
       ) : null);
     }
     // Merge with `_pendingState` if it exists, otherwise with existing state.
     this.replaceState(
@@ -6040,17 +6639,25 @@ var ReactCompositeComponentMixin = {
    * @param {object} completeState Next state.
    * @param {?function} callback Called after state is updated.
    * @final
    * @protected
    */
   replaceState: function(completeState, callback) {
     validateLifeCycleOnReplaceState(this);
     this._pendingState = completeState;
-    ReactUpdates.enqueueUpdate(this, callback);
+    if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) {
+      // If we're in a componentWillMount handler, don't enqueue a rerender
+      // because ReactUpdates assumes we're in a browser context (which is wrong
+      // for server rendering) and we're about to do a render anyway.
+      // TODO: The callback here is ignored when setState is called from
+      // componentWillMount. Either fix it or disallow doing so completely in
+      // favor of getInitialState.
+      ReactUpdates.enqueueUpdate(this, callback);
+    }
   },
 
   /**
    * Filters the context object to only contain keys specified in
    * `contextTypes`, and asserts that they are valid.
    *
    * @param {object} context
    * @return {?object}
@@ -6115,22 +6722,27 @@ var ReactCompositeComponentMixin = {
    * asserting that the props are valid. Does not mutate its argument; returns
    * a new props object with defaults merged in.
    *
    * @param {object} newProps
    * @return {object}
    * @private
    */
   _processProps: function(newProps) {
-    var props = merge(newProps);
-    var defaultProps = this._defaultProps;
-    for (var propName in defaultProps) {
-      if (typeof props[propName] === 'undefined') {
-        props[propName] = defaultProps[propName];
-      }
+    var defaultProps = this.constructor.defaultProps;
+    var props;
+    if (defaultProps) {
+      props = merge(newProps);
+      for (var propName in defaultProps) {
+        if (typeof props[propName] === 'undefined') {
+          props[propName] = defaultProps[propName];
+        }
+      }
+    } else {
+      props = newProps;
     }
     if ("production" !== "development") {
       var propTypes = this.constructor.propTypes;
       if (propTypes) {
         this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
       }
     }
     return props;
@@ -6140,210 +6752,220 @@ var ReactCompositeComponentMixin = {
    * Assert that the props are valid
    *
    * @param {object} propTypes Map of prop name to a ReactPropType
    * @param {object} props
    * @param {string} location e.g. "prop", "context", "child context"
    * @private
    */
   _checkPropTypes: function(propTypes, props, location) {
+    // TODO: Stop validating prop types here and only use the descriptor
+    // validation.
     var componentName = this.constructor.displayName;
     for (var propName in propTypes) {
       if (propTypes.hasOwnProperty(propName)) {
-        propTypes[propName](props, propName, componentName, location);
-      }
-    }
-  },
-
-  performUpdateIfNecessary: function() {
+        var error =
+          propTypes[propName](props, propName, componentName, location);
+        if (error instanceof Error) {
+          // We may want to extend this logic for similar errors in
+          // renderComponent calls, so I'm abstracting it away into
+          // a function to minimize refactoring in the future
+          var addendum = getDeclarationErrorAddendum(this);
+          ("production" !== "development" ? warning(false, error.message + addendum) : null);
+        }
+      }
+    }
+  },
+
+  /**
+   * If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate`
+   * is set, update the component.
+   *
+   * @param {ReactReconcileTransaction} transaction
+   * @internal
+   */
+  performUpdateIfNecessary: function(transaction) {
     var compositeLifeCycleState = this._compositeLifeCycleState;
     // Do not trigger a state transition if we are in the middle of mounting or
     // receiving props because both of those will already be doing this.
     if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
         compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
       return;
     }
-    ReactComponent.Mixin.performUpdateIfNecessary.call(this);
-  },
-
-  /**
-   * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
-   * set, update the component.
-   *
-   * @param {ReactReconcileTransaction} transaction
-   * @internal
-   */
-  _performUpdateIfNecessary: function(transaction) {
-    if (this._pendingProps == null &&
+
+    if (this._pendingDescriptor == null &&
         this._pendingState == null &&
-        this._pendingContext == null &&
         !this._pendingForceUpdate) {
       return;
     }
 
-    var nextFullContext = this._pendingContext || this._currentContext;
-    var nextContext = this._processContext(nextFullContext);
-    this._pendingContext = null;
-
+    var nextContext = this.context;
     var nextProps = this.props;
-    if (this._pendingProps != null) {
-      nextProps = this._processProps(this._pendingProps);
-      this._pendingProps = null;
+    var nextDescriptor = this._descriptor;
+    if (this._pendingDescriptor != null) {
+      nextDescriptor = this._pendingDescriptor;
+      nextContext = this._processContext(nextDescriptor._context);
+      nextProps = this._processProps(nextDescriptor.props);
+      this._pendingDescriptor = null;
 
       this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
       if (this.componentWillReceiveProps) {
         this.componentWillReceiveProps(nextProps, nextContext);
       }
     }
 
     this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
 
-    // Unlike props, state, and context, we specifically don't want to set
-    // _pendingOwner to null here because it's possible for a component to have
-    // a null owner, so we instead make `this._owner === this._pendingOwner`
-    // mean that there's no owner change pending.
-    var nextOwner = this._pendingOwner;
-
     var nextState = this._pendingState || this.state;
     this._pendingState = null;
 
     try {
-      if (this._pendingForceUpdate ||
-          !this.shouldComponentUpdate ||
-          this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
+      var shouldUpdate =
+        this._pendingForceUpdate ||
+        !this.shouldComponentUpdate ||
+        this.shouldComponentUpdate(nextProps, nextState, nextContext);
+
+      if ("production" !== "development") {
+        if (typeof shouldUpdate === "undefined") {
+          console.warn(
+            (this.constructor.displayName || 'ReactCompositeComponent') +
+            '.shouldComponentUpdate(): Returned undefined instead of a ' +
+            'boolean value. Make sure to return true or false.'
+          );
+        }
+      }
+
+      if (shouldUpdate) {
         this._pendingForceUpdate = false;
         // Will set `this.props`, `this.state` and `this.context`.
         this._performComponentUpdate(
+          nextDescriptor,
           nextProps,
-          nextOwner,
           nextState,
-          nextFullContext,
           nextContext,
           transaction
         );
       } else {
         // If it's determined that a component should not update, we still want
         // to set props and state.
+        this._descriptor = nextDescriptor;
         this.props = nextProps;
-        this._owner = nextOwner;
         this.state = nextState;
-        this._currentContext = nextFullContext;
         this.context = nextContext;
+
+        // Owner cannot change because shouldUpdateReactComponent doesn't allow
+        // it. TODO: Remove this._owner completely.
+        this._owner = nextDescriptor._owner;
       }
     } finally {
       this._compositeLifeCycleState = null;
     }
   },
 
   /**
    * Merges new props and state, notifies delegate methods of update and
    * performs update.
    *
-   * @param {object} nextProps Next object to set as properties.
-   * @param {?ReactComponent} nextOwner Next component to set as owner
+   * @param {ReactDescriptor} nextDescriptor Next descriptor
+   * @param {object} nextProps Next public object to set as properties.
    * @param {?object} nextState Next object to set as state.
-   * @param {?object} nextFullContext Next object to set as _currentContext.
-   * @param {?object} nextContext Next object to set as context.
+   * @param {?object} nextContext Next public object to set as context.
    * @param {ReactReconcileTransaction} transaction
    * @private
    */
   _performComponentUpdate: function(
+    nextDescriptor,
     nextProps,
-    nextOwner,
     nextState,
-    nextFullContext,
     nextContext,
     transaction
   ) {
+    var prevDescriptor = this._descriptor;
     var prevProps = this.props;
-    var prevOwner = this._owner;
     var prevState = this.state;
     var prevContext = this.context;
 
     if (this.componentWillUpdate) {
       this.componentWillUpdate(nextProps, nextState, nextContext);
     }
 
+    this._descriptor = nextDescriptor;
     this.props = nextProps;
-    this._owner = nextOwner;
     this.state = nextState;
-    this._currentContext = nextFullContext;
     this.context = nextContext;
 
+    // Owner cannot change because shouldUpdateReactComponent doesn't allow
+    // it. TODO: Remove this._owner completely.
+    this._owner = nextDescriptor._owner;
+
     this.updateComponent(
       transaction,
-      prevProps,
-      prevOwner,
-      prevState,
-      prevContext
+      prevDescriptor
     );
 
     if (this.componentDidUpdate) {
       transaction.getReactMountReady().enqueue(
-        this,
-        this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
+        this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
+        this
       );
     }
   },
 
-  receiveComponent: function(nextComponent, transaction) {
-    if (nextComponent === this._descriptor) {
-      // Since props and context are immutable after the component is
-      // mounted, we can do a cheap identity compare here to determine
-      // if this is a superfluous reconcile.
+  receiveComponent: function(nextDescriptor, transaction) {
+    if (nextDescriptor === this._descriptor &&
+        nextDescriptor._owner != null) {
+      // Since descriptors are immutable after the owner is rendered,
+      // we can do a cheap identity compare here to determine if this is a
+      // superfluous reconcile. It's possible for state to be mutable but such
+      // change should trigger an update of the owner which would recreate
+      // the descriptor. We explicitly check for the existence of an owner since
+      // it's possible for a descriptor created outside a composite to be
+      // deeply mutated and reused.
       return;
     }
 
-    // Update the descriptor that was last used by this component instance
-    this._descriptor = nextComponent;
-
-    this._pendingContext = nextComponent._currentContext;
     ReactComponent.Mixin.receiveComponent.call(
       this,
-      nextComponent,
+      nextDescriptor,
       transaction
     );
   },
 
   /**
    * Updates the component's currently mounted DOM representation.
    *
    * By default, this implements React's rendering and reconciliation algorithm.
    * Sophisticated clients may wish to override this.
    *
    * @param {ReactReconcileTransaction} transaction
-   * @param {object} prevProps
-   * @param {?ReactComponent} prevOwner
-   * @param {?object} prevState
-   * @param {?object} prevContext
+   * @param {ReactDescriptor} prevDescriptor
    * @internal
    * @overridable
    */
   updateComponent: ReactPerf.measure(
     'ReactCompositeComponent',
     'updateComponent',
-    function(transaction, prevProps, prevOwner, prevState, prevContext) {
+    function(transaction, prevParentDescriptor) {
       ReactComponent.Mixin.updateComponent.call(
         this,
         transaction,
-        prevProps,
-        prevOwner
+        prevParentDescriptor
       );
 
-
       var prevComponentInstance = this._renderedComponent;
-      var nextComponent = this._renderValidatedComponent();
-      if (shouldUpdateReactComponent(prevComponentInstance, nextComponent)) {
-        prevComponentInstance.receiveComponent(nextComponent, transaction);
+      var prevDescriptor = prevComponentInstance._descriptor;
+      var nextDescriptor = this._renderValidatedComponent();
+      if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
+        prevComponentInstance.receiveComponent(nextDescriptor, transaction);
       } else {
         // These two IDs are actually the same! But nothing should rely on that.
         var thisID = this._rootNodeID;
         var prevComponentID = prevComponentInstance._rootNodeID;
         prevComponentInstance.unmountComponent();
-        this._renderedComponent = instantiateReactComponent(nextComponent);
+        this._renderedComponent = instantiateReactComponent(nextDescriptor);
         var nextMarkup = this._renderedComponent.mountComponent(
           thisID,
           transaction,
           this._mountDepth + 1
         );
         ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
           prevComponentID,
           nextMarkup
@@ -6390,30 +7012,38 @@ var ReactCompositeComponentMixin = {
    * @private
    */
   _renderValidatedComponent: ReactPerf.measure(
     'ReactCompositeComponent',
     '_renderValidatedComponent',
     function() {
       var renderedComponent;
       var previousContext = ReactContext.current;
-      ReactContext.current = this._processChildContext(this._currentContext);
+      ReactContext.current = this._processChildContext(
+        this._descriptor._context
+      );
       ReactCurrentOwner.current = this;
       try {
         renderedComponent = this.render();
+        if (renderedComponent === null || renderedComponent === false) {
+          renderedComponent = ReactEmptyComponent.getEmptyComponent();
+          ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
+        } else {
+          ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
+        }
       } finally {
         ReactContext.current = previousContext;
         ReactCurrentOwner.current = null;
       }
       ("production" !== "development" ? invariant(
-        ReactComponent.isValidComponent(renderedComponent),
+        ReactDescriptor.isValidDescriptor(renderedComponent),
         '%s.render(): A valid ReactComponent must be returned. You may have ' +
-          'returned null, undefined, an array, or some other invalid object.',
+          'returned undefined, an array or some other invalid object.',
         this.constructor.displayName || 'ReactCompositeComponent'
-      ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
+      ) : invariant(ReactDescriptor.isValidDescriptor(renderedComponent)));
       return renderedComponent;
     }
   ),
 
   /**
    * @private
    */
   _bindAutoBindMethods: function() {
@@ -6478,28 +7108,16 @@ var ReactCompositeComponentMixin = {
 
 var ReactCompositeComponentBase = function() {};
 mixInto(ReactCompositeComponentBase, ReactComponent.Mixin);
 mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
 mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
 mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
 
 /**
- * Checks if a value is a valid component constructor.
- *
- * @param {*}
- * @return {boolean}
- * @public
- */
-function isValidClass(componentClass) {
-  return componentClass instanceof Function &&
-         'componentConstructor' in componentClass &&
-         componentClass.componentConstructor instanceof Function;
-}
-/**
  * Module for creating composite components.
  *
  * @class ReactCompositeComponent
  * @extends ReactComponent
  * @extends ReactOwner
  * @extends ReactPropTransferer
  */
 var ReactCompositeComponent = {
@@ -6511,36 +7129,32 @@ var ReactCompositeComponent = {
   /**
    * Creates a composite component class given a class specification.
    *
    * @param {object} spec Class specification (which must define `render`).
    * @return {function} Component constructor function.
    * @public
    */
   createClass: function(spec) {
-    var Constructor = function() {};
+    var Constructor = function(props, owner) {
+      this.construct(props, owner);
+    };
     Constructor.prototype = new ReactCompositeComponentBase();
     Constructor.prototype.constructor = Constructor;
 
-    var DescriptorConstructor = Constructor;
-
-    var ConvenienceConstructor = function(props, children) {
-      var descriptor = new DescriptorConstructor();
-      descriptor.construct.apply(descriptor, arguments);
-      return descriptor;
-    };
-    ConvenienceConstructor.componentConstructor = Constructor;
-    Constructor.ConvenienceConstructor = ConvenienceConstructor;
-    ConvenienceConstructor.originalSpec = spec;
-
     injectedMixins.forEach(
-      mixSpecIntoComponent.bind(null, ConvenienceConstructor)
-    );
-
-    mixSpecIntoComponent(ConvenienceConstructor, spec);
+      mixSpecIntoComponent.bind(null, Constructor)
+    );
+
+    mixSpecIntoComponent(Constructor, spec);
+
+    // Initialize the defaultProps property after all mixins have been merged
+    if (Constructor.getDefaultProps) {
+      Constructor.defaultProps = Constructor.getDefaultProps();
+    }
 
     ("production" !== "development" ? invariant(
       Constructor.prototype.render,
       'createClass(...): Class specification must implement a `render` method.'
     ) : invariant(Constructor.prototype.render));
 
     if ("production" !== "development") {
       if (Constructor.prototype.componentShouldUpdate) {
@@ -6552,53 +7166,46 @@ var ReactCompositeComponent = {
           (spec.displayName || 'A component') + ' has a method called ' +
           'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
           'The name is phrased as a question because the function is ' +
           'expected to return a value.'
          );
       }
     }
 
-    // Expose the convience constructor on the prototype so that it can be
-    // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
-    // static methods like <Foo />.type.staticMethod();
-    // This should not be named constructor since this may not be the function
-    // that created the descriptor, and it may not even be a constructor.
-    ConvenienceConstructor.type = Constructor;
-    Constructor.prototype.type = Constructor;
-
     // Reduce time spent doing lookups by setting these on the prototype.
     for (var methodName in ReactCompositeComponentInterface) {
       if (!Constructor.prototype[methodName]) {
         Constructor.prototype[methodName] = null;
       }
     }
 
+    var descriptorFactory = ReactDescriptor.createFactory(Constructor);
+
     if ("production" !== "development") {
-      // In DEV the convenience constructor generates a proxy to another
-      // instance around it to warn about access to properties on the
-      // descriptor.
-      DescriptorConstructor = createDescriptorProxy(Constructor);
-    }
-
-    return ConvenienceConstructor;
-  },
-
-  isValidClass: isValidClass,
+      return ReactDescriptorValidator.createFactory(
+        descriptorFactory,
+        Constructor.propTypes,
+        Constructor.contextTypes
+      );
+    }
+
+    return descriptorFactory;
+  },
 
   injection: {
     injectMixin: function(mixin) {
       injectedMixins.push(mixin);
     }
   }
 };
 
 module.exports = ReactCompositeComponent;
 
-},{"./ReactComponent":31,"./ReactContext":34,"./ReactCurrentOwner":35,"./ReactErrorUtils":51,"./ReactOwner":64,"./ReactPerf":65,"./ReactPropTransferer":66,"./ReactPropTypeLocationNames":67,"./ReactPropTypeLocations":68,"./ReactUpdates":81,"./instantiateReactComponent":124,"./invariant":125,"./keyMirror":131,"./merge":134,"./mixInto":137,"./monitorCodeUse":138,"./objMap":139,"./shouldUpdateReactComponent":144,"./warning":148}],34:[function(_dereq_,module,exports){
+},{"./ReactComponent":35,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactDescriptorValidator":57,"./ReactEmptyComponent":58,"./ReactErrorUtils":59,"./ReactOwner":70,"./ReactPerf":71,"./ReactPropTransferer":72,"./ReactPropTypeLocationNames":73,"./ReactPropTypeLocations":74,"./ReactUpdates":87,"./instantiateReactComponent":133,"./invariant":134,"./keyMirror":140,"./mapObject":142,"./merge":144,"./mixInto":147,"./monitorCodeUse":148,"./shouldUpdateReactComponent":154,"./warning":158}],39:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -6657,17 +7264,17 @@ var ReactContext = {
     }
     return result;
   }
 
 };
 
 module.exports = ReactContext;
 
-},{"./merge":134}],35:[function(_dereq_,module,exports){
+},{"./merge":144}],40:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -6698,17 +7305,17 @@ var ReactCurrentOwner = {
    * @type {ReactComponent}
    */
   current: null
 
 };
 
 module.exports = ReactCurrentOwner;
 
-},{}],36:[function(_dereq_,module,exports){
+},{}],41:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -6720,66 +7327,64 @@ module.exports = ReactCurrentOwner;
  * limitations under the License.
  *
  * @providesModule ReactDOM
  * @typechecks static-only
  */
 
 "use strict";
 
+var ReactDescriptor = _dereq_("./ReactDescriptor");
+var ReactDescriptorValidator = _dereq_("./ReactDescriptorValidator");
 var ReactDOMComponent = _dereq_("./ReactDOMComponent");
 
 var mergeInto = _dereq_("./mergeInto");
-var objMapKeyVal = _dereq_("./objMapKeyVal");
+var mapObject = _dereq_("./mapObject");
 
 /**
  * Creates a new React class that is idempotent and capable of containing other
  * React components. It accepts event listeners and DOM properties that are
  * valid according to `DOMProperty`.
  *
  *  - Event listeners: `onClick`, `onMouseDown`, etc.
  *  - DOM properties: `className`, `name`, `title`, etc.
  *
  * The `style` property functions differently from the DOM API. It accepts an
  * object mapping of style properties to values.
  *
+ * @param {boolean} omitClose True if the close tag should be omitted.
  * @param {string} tag Tag name (e.g. `div`).
- * @param {boolean} omitClose True if the close tag should be omitted.
  * @private
  */
-function createDOMComponentClass(tag, omitClose) {
-  var Constructor = function() {};
+function createDOMComponentClass(omitClose, tag) {
+  var Constructor = function(descriptor) {
+    this.construct(descriptor);
+  };
   Constructor.prototype = new ReactDOMComponent(tag, omitClose);
   Constructor.prototype.constructor = Constructor;
   Constructor.displayName = tag;
 
-  var ConvenienceConstructor = function(props, children) {
-    var instance = new Constructor();
-    instance.construct.apply(instance, arguments);
-    return instance;
-  };
-
-  // Expose the constructor on the ConvenienceConstructor and prototype so that
-  // it can be easily easily accessed on descriptors.
-  // E.g. <div />.type === div.type
-  ConvenienceConstructor.type = Constructor;
-  Constructor.prototype.type = Constructor;
-
-  Constructor.ConvenienceConstructor = ConvenienceConstructor;
-  ConvenienceConstructor.componentConstructor = Constructor;
+  var ConvenienceConstructor = ReactDescriptor.createFactory(Constructor);
+
+  if ("production" !== "development") {
+    return ReactDescriptorValidator.createFactory(
+      ConvenienceConstructor
+    );
+  }
+
   return ConvenienceConstructor;
 }
 
 /**
  * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
  * This is also accessible via `React.DOM`.
  *
  * @public
  */
-var ReactDOM = objMapKeyVal({
+var ReactDOM = mapObject({
   a: false,
   abbr: false,
   address: false,
   area: true,
   article: false,
   aside: false,
   audio: false,
   b: false,
@@ -6884,40 +7489,44 @@ var ReactDOM = objMapKeyVal({
   ul: false,
   'var': false,
   video: false,
   wbr: true,
 
   // SVG
   circle: false,
   defs: false,
+  ellipse: false,
   g: false,
   line: false,
   linearGradient: false,
+  mask: false,
   path: false,
+  pattern: false,
   polygon: false,
   polyline: false,
   radialGradient: false,
   rect: false,
   stop: false,
   svg: false,
-  text: false
+  text: false,
+  tspan: false
 }, createDOMComponentClass);
 
 var injection = {
   injectComponentClasses: function(componentClasses) {
     mergeInto(ReactDOM, componentClasses);
   }
 };
 
 ReactDOM.injection = injection;
 
 module.exports = ReactDOM;
 
-},{"./ReactDOMComponent":38,"./mergeInto":136,"./objMapKeyVal":140}],37:[function(_dereq_,module,exports){
+},{"./ReactDOMComponent":43,"./ReactDescriptor":56,"./ReactDescriptorValidator":57,"./mapObject":142,"./mergeInto":146}],42:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -6978,17 +7587,17 @@ var ReactDOMButton = ReactCompositeCompo
 
     return button(props, this.props.children);
   }
 
 });
 
 module.exports = ReactDOMButton;
 
-},{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./keyMirror":131}],38:[function(_dereq_,module,exports){
+},{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./keyMirror":140}],43:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7005,30 +7614,30 @@ module.exports = ReactDOMButton;
 
 "use strict";
 
 var CSSPropertyOperations = _dereq_("./CSSPropertyOperations");
 var DOMProperty = _dereq_("./DOMProperty");
 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
 var ReactComponent = _dereq_("./ReactComponent");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
+var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
 var ReactMount = _dereq_("./ReactMount");
 var ReactMultiChild = _dereq_("./ReactMultiChild");
 var ReactPerf = _dereq_("./ReactPerf");
 
 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser");
 var invariant = _dereq_("./invariant");
 var keyOf = _dereq_("./keyOf");
 var merge = _dereq_("./merge");
 var mixInto = _dereq_("./mixInto");
 
-var deleteListener = ReactEventEmitter.deleteListener;
-var listenTo = ReactEventEmitter.listenTo;
-var registrationNameModules = ReactEventEmitter.registrationNameModules;
+var deleteListener = ReactBrowserEventEmitter.deleteListener;
+var listenTo = ReactBrowserEventEmitter.listenTo;
+var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
 
 // For quickly matching children type, to test if can be treated as content.
 var CONTENT_TYPES = {'string': true, 'number': true};
 
 var STYLE = keyOf({style: null});
 
 var ELEMENT_NODE_TYPE = 1;
 
@@ -7128,17 +7737,17 @@ ReactDOMComponent.Mixin = {
     for (var propKey in props) {
       if (!props.hasOwnProperty(propKey)) {
         continue;
       }
       var propValue = props[propKey];
       if (propValue == null) {
         continue;
       }
-      if (registrationNameModules[propKey]) {
+      if (registrationNameModules.hasOwnProperty(propKey)) {
         putListener(this._rootNodeID, propKey, propValue, transaction);
       } else {
         if (propKey === STYLE) {
           if (propValue) {
             propValue = props.style = merge(props.style);
           }
           propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
         }
@@ -7186,55 +7795,57 @@ ReactDOMComponent.Mixin = {
           transaction
         );
         return mountImages.join('');
       }
     }
     return '';
   },
 
-  receiveComponent: function(nextComponent, transaction) {
-    if (nextComponent === this) {
-      // Since props and context are immutable after the component is
-      // mounted, we can do a cheap identity compare here to determine
-      // if this is a superfluous reconcile.
-
-      // TODO: compare the descriptor
+  receiveComponent: function(nextDescriptor, transaction) {
+    if (nextDescriptor === this._descriptor &&
+        nextDescriptor._owner != null) {
+      // Since descriptors are immutable after the owner is rendered,
+      // we can do a cheap identity compare here to determine if this is a
+      // superfluous reconcile. It's possible for state to be mutable but such
+      // change should trigger an update of the owner which would recreate
+      // the descriptor. We explicitly check for the existence of an owner since
+      // it's possible for a descriptor created outside a composite to be
+      // deeply mutated and reused.
       return;
     }
 
-    assertValidProps(nextComponent.props);
     ReactComponent.Mixin.receiveComponent.call(
       this,
-      nextComponent,
+      nextDescriptor,
       transaction
     );
   },
 
   /**
    * Updates a native DOM component after it has already been allocated and
    * attached to the DOM. Reconciles the root DOM node, then recurses.
    *
    * @param {ReactReconcileTransaction} transaction
-   * @param {object} prevProps
+   * @param {ReactDescriptor} prevDescriptor
    * @internal
    * @overridable
    */
   updateComponent: ReactPerf.measure(
     'ReactDOMComponent',
     'updateComponent',
-    function(transaction, prevProps, prevOwner) {
+    function(transaction, prevDescriptor) {
+      assertValidProps(this._descriptor.props);
       ReactComponent.Mixin.updateComponent.call(
         this,
         transaction,
-        prevProps,
-        prevOwner
+        prevDescriptor
       );
-      this._updateDOMProperties(prevProps, transaction);
-      this._updateDOMChildren(prevProps, transaction);
+      this._updateDOMProperties(prevDescriptor.props, transaction);
+      this._updateDOMChildren(prevDescriptor.props, transaction);
     }
   ),
 
   /**
    * Reconciles the properties by detecting differences in property values and
    * updating the DOM as necessary. This function is probably the single most
    * critical path for performance optimization.
    *
@@ -7261,17 +7872,17 @@ ReactDOMComponent.Mixin = {
       if (propKey === STYLE) {
         var lastStyle = lastProps[propKey];
         for (styleName in lastStyle) {
           if (lastStyle.hasOwnProperty(styleName)) {
             styleUpdates = styleUpdates || {};
             styleUpdates[styleName] = '';
           }
         }
-      } else if (registrationNameModules[propKey]) {
+      } else if (registrationNameModules.hasOwnProperty(propKey)) {
         deleteListener(this._rootNodeID, propKey);
       } else if (
           DOMProperty.isStandardName[propKey] ||
           DOMProperty.isCustomAttribute(propKey)) {
         ReactComponent.BackendIDOperations.deletePropertyByID(
           this._rootNodeID,
           propKey
         );
@@ -7286,34 +7897,34 @@ ReactDOMComponent.Mixin = {
       if (propKey === STYLE) {
         if (nextProp) {
           nextProp = nextProps.style = merge(nextProp);
         }
         if (lastProp) {
           // Unset styles on `lastProp` but not on `nextProp`.
           for (styleName in lastProp) {
             if (lastProp.hasOwnProperty(styleName) &&
-                !nextProp.hasOwnProperty(styleName)) {
+                (!nextProp || !nextProp.hasOwnProperty(styleName))) {
               styleUpdates = styleUpdates || {};
               styleUpdates[styleName] = '';
             }
           }
           // Update styles that changed since `lastProp`.
           for (styleName in nextProp) {
             if (nextProp.hasOwnProperty(styleName) &&
                 lastProp[styleName] !== nextProp[styleName]) {
               styleUpdates = styleUpdates || {};
               styleUpdates[styleName] = nextProp[styleName];
             }
           }
         } else {
           // Relies on `updateStylesByID` not mutating `styleUpdates`.
           styleUpdates = nextProp;
         }
-      } else if (registrationNameModules[propKey]) {
+      } else if (registrationNameModules.hasOwnProperty(propKey)) {
         putListener(this._rootNodeID, propKey, nextProp, transaction);
       } else if (
           DOMProperty.isStandardName[propKey] ||
           DOMProperty.isCustomAttribute(propKey)) {
         ReactComponent.BackendIDOperations.updatePropertyByID(
           this._rootNodeID,
           propKey,
           nextProp
@@ -7383,30 +7994,30 @@ ReactDOMComponent.Mixin = {
   /**
    * Destroys all event registrations for this instance. Does not remove from
    * the DOM. That must be done by the parent.
    *
    * @internal
    */
   unmountComponent: function() {
     this.unmountChildren();
-    ReactEventEmitter.deleteAllListeners(this._rootNodeID);
+    ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
     ReactComponent.Mixin.unmountComponent.call(this);
   }
 
 };
 
 mixInto(ReactDOMComponent, ReactComponent.Mixin);
 mixInto(ReactDOMComponent, ReactDOMComponent.Mixin);
 mixInto(ReactDOMComponent, ReactMultiChild.Mixin);
 mixInto(ReactDOMComponent, ReactBrowserComponentMixin);
 
 module.exports = ReactDOMComponent;
 
-},{"./CSSPropertyOperations":4,"./DOMProperty":9,"./DOMPropertyOperations":10,"./ReactBrowserComponentMixin":27,"./ReactComponent":31,"./ReactEventEmitter":52,"./ReactMount":60,"./ReactMultiChild":62,"./ReactPerf":65,"./escapeTextForBrowser":111,"./invariant":125,"./keyOf":132,"./merge":134,"./mixInto":137}],39:[function(_dereq_,module,exports){
+},{"./CSSPropertyOperations":5,"./DOMProperty":11,"./DOMPropertyOperations":12,"./ReactBrowserComponentMixin":30,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactMount":67,"./ReactMultiChild":68,"./ReactPerf":71,"./escapeTextForBrowser":118,"./invariant":134,"./keyOf":141,"./merge":144,"./mixInto":147}],44:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7417,60 +8028,52 @@ module.exports = ReactDOMComponent;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactDOMForm
  */
 
 "use strict";
 
+var EventConstants = _dereq_("./EventConstants");
+var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin");
 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
 var ReactDOM = _dereq_("./ReactDOM");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
-var EventConstants = _dereq_("./EventConstants");
 
 // Store a reference to the <form> `ReactDOMComponent`.
 var form = ReactDOM.form;
 
 /**
  * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need
  * to capture it on the <form> element itself. There are lots of hacks we could
  * do to accomplish this, but the most reliable is to make <form> a
  * composite component and use `componentDidMount` to attach the event handlers.
  */
 var ReactDOMForm = ReactCompositeComponent.createClass({
   displayName: 'ReactDOMForm',
 
-  mixins: [ReactBrowserComponentMixin],
+  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
 
   render: function() {
     // TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
     // `jshint` fails to parse JSX so in order for linting to work in the open
     // source repo, we need to just use `ReactDOM.form`.
     return this.transferPropsTo(form(null, this.props.children));
   },
 
   componentDidMount: function() {
-    ReactEventEmitter.trapBubbledEvent(
-      EventConstants.topLevelTypes.topReset,
-      'reset',
-      this.getDOMNode()
-    );
-    ReactEventEmitter.trapBubbledEvent(
-      EventConstants.topLevelTypes.topSubmit,
-      'submit',
-      this.getDOMNode()
-    );
+    this.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset');
+    this.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit');
   }
 });
 
 module.exports = ReactDOMForm;
 
-},{"./EventConstants":15,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactEventEmitter":52}],40:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],45:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7491,31 +8094,30 @@ module.exports = ReactDOMForm;
 
 var CSSPropertyOperations = _dereq_("./CSSPropertyOperations");
 var DOMChildrenOperations = _dereq_("./DOMChildrenOperations");
 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
 var ReactMount = _dereq_("./ReactMount");
 var ReactPerf = _dereq_("./ReactPerf");
 
 var invariant = _dereq_("./invariant");
+var setInnerHTML = _dereq_("./setInnerHTML");
 
 /**
  * Errors for properties that should not be updated with `updatePropertyById()`.
  *
  * @type {object}
  * @private
  */
 var INVALID_PROPERTY_ERRORS = {
   dangerouslySetInnerHTML:
     '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
   style: '`style` must be set using `updateStylesByID()`.'
 };
 
-var useWhitespaceWorkaround;
-
 /**
  * Operations used to process updates to DOM nodes. This is made injectable via
  * `ReactComponent.BackendIDOperations`.
  */
 var ReactDOMIDOperations = {
 
   /**
    * Updates a DOM node with new property values. This should only be used to
@@ -7594,45 +8196,17 @@ var ReactDOMIDOperations = {
    * @param {string} html An HTML string.
    * @internal
    */
   updateInnerHTMLByID: ReactPerf.measure(
     'ReactDOMIDOperations',
     'updateInnerHTMLByID',
     function(id, html) {
       var node = ReactMount.getNode(id);
-
-      // IE8: When updating a just created node with innerHTML only leading
-      // whitespace is removed. When updating an existing node with innerHTML
-      // whitespace in root TextNodes is also collapsed.
-      // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
-
-      if (useWhitespaceWorkaround === undefined) {
-        // Feature detection; only IE8 is known to behave improperly like this.
-        var temp = document.createElement('div');
-        temp.innerHTML = ' ';
-        useWhitespaceWorkaround = temp.innerHTML === '';
-      }
-
-      if (useWhitespaceWorkaround) {
-        // Magic theory: IE8 supposedly differentiates between added and updated
-        // nodes when processing innerHTML, innerHTML on updated nodes suffers
-        // from worse whitespace behavior. Re-adding a node like this triggers
-        // the initial and more favorable whitespace behavior.
-        node.parentNode.replaceChild(node, node);
-      }
-
-      if (useWhitespaceWorkaround && html.match(/^[ \r\n\t\f]/)) {
-        // Recover leading whitespace by temporarily prepending any character.
-        // \uFEFF has the potential advantage of being zero-width/invisible.
-        node.innerHTML = '\uFEFF' + html;
-        node.firstChild.deleteData(0, 1);
-      } else {
-        node.innerHTML = html;
-      }
+      setInnerHTML(node, html);
     }
   ),
 
   /**
    * Updates a DOM node's text content set by `props.content`.
    *
    * @param {string} id ID of the node to update.
    * @param {string} content Text content.
@@ -7680,17 +8254,17 @@ var ReactDOMIDOperations = {
       }
       DOMChildrenOperations.processUpdates(updates, markup);
     }
   )
 };
 
 module.exports = ReactDOMIDOperations;
 
-},{"./CSSPropertyOperations":4,"./DOMChildrenOperations":8,"./DOMPropertyOperations":10,"./ReactMount":60,"./ReactPerf":65,"./invariant":125}],41:[function(_dereq_,module,exports){
+},{"./CSSPropertyOperations":5,"./DOMChildrenOperations":10,"./DOMPropertyOperations":12,"./ReactMount":67,"./ReactPerf":71,"./invariant":134,"./setInnerHTML":152}],46:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7701,59 +8275,50 @@ module.exports = ReactDOMIDOperations;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactDOMImg
  */
 
 "use strict";
 
+var EventConstants = _dereq_("./EventConstants");
+var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin");
 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
 var ReactDOM = _dereq_("./ReactDOM");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
-var EventConstants = _dereq_("./EventConstants");
 
 // Store a reference to the <img> `ReactDOMComponent`.
 var img = ReactDOM.img;
 
 /**
  * Since onLoad doesn't bubble OR capture on the top level in IE8, we need to
  * capture it on the <img> element itself. There are lots of hacks we could do
  * to accomplish this, but the most reliable is to make <img> a composite
  * component and use `componentDidMount` to attach the event handlers.
  */
 var ReactDOMImg = ReactCompositeComponent.createClass({
   displayName: 'ReactDOMImg',
   tagName: 'IMG',
 
-  mixins: [ReactBrowserComponentMixin],
+  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
 
   render: function() {
     return img(this.props);
   },
 
   componentDidMount: function() {
-    var node = this.getDOMNode();
-    ReactEventEmitter.trapBubbledEvent(
-      EventConstants.topLevelTypes.topLoad,
-      'load',
-      node
-    );
-    ReactEventEmitter.trapBubbledEvent(
-      EventConstants.topLevelTypes.topError,
-      'error',
-      node
-    );
+    this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
+    this.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error');
   }
 });
 
 module.exports = ReactDOMImg;
 
-},{"./EventConstants":15,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactEventEmitter":52}],42:[function(_dereq_,module,exports){
+},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],47:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7927,17 +8492,17 @@ var ReactDOMInput = ReactCompositeCompon
 
     return returnValue;
   }
 
 });
 
 module.exports = ReactDOMInput;
 
-},{"./AutoFocusMixin":1,"./DOMPropertyOperations":10,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactMount":60,"./invariant":125,"./merge":134}],43:[function(_dereq_,module,exports){
+},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactMount":67,"./invariant":134,"./merge":144}],48:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -7984,17 +8549,17 @@ var ReactDOMOption = ReactCompositeCompo
   render: function() {
     return option(this.props, this.props.children);
   }
 
 });
 
 module.exports = ReactDOMOption;
 
-},{"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./warning":148}],44:[function(_dereq_,module,exports){
+},{"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./warning":158}],49:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8011,44 +8576,43 @@ module.exports = ReactDOMOption;
 "use strict";
 
 var AutoFocusMixin = _dereq_("./AutoFocusMixin");
 var LinkedValueUtils = _dereq_("./LinkedValueUtils");
 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
 var ReactDOM = _dereq_("./ReactDOM");
 
-var invariant = _dereq_("./invariant");
 var merge = _dereq_("./merge");
 
 // Store a reference to the <select> `ReactDOMComponent`.
 var select = ReactDOM.select;
 
 /**
  * Validation function for `value` and `defaultValue`.
  * @private
  */
 function selectValueType(props, propName, componentName) {
   if (props[propName] == null) {
     return;
   }
   if (props.multiple) {
-    ("production" !== "development" ? invariant(
-      Array.isArray(props[propName]),
-      'The `%s` prop supplied to <select> must be an array if `multiple` is ' +
-      'true.',
-      propName
-    ) : invariant(Array.isArray(props[propName])));
+    if (!Array.isArray(props[propName])) {
+      return new Error(
+        ("The `" + propName + "` prop supplied to <select> must be an array if ") +
+        ("`multiple` is true.")
+      );
+    }
   } else {
-    ("production" !== "development" ? invariant(
-      !Array.isArray(props[propName]),
-      'The `%s` prop supplied to <select> must be a scalar value if ' +
-      '`multiple` is false.',
-      propName
-    ) : invariant(!Array.isArray(props[propName])));
+    if (Array.isArray(props[propName])) {
+      return new Error(
+        ("The `" + propName + "` prop supplied to <select> must be a scalar ") +
+        ("value if `multiple` is false.")
+      );
+    }
   }
 }
 
 /**
  * If `value` is supplied, updates <option> elements on mount and update.
  * @param {ReactComponent} component Instance of ReactDOMSelect
  * @param {?*} propValue For uncontrolled components, null/undefined. For
  * controlled components, a string (or with `multiple`, a list of strings).
@@ -8129,19 +8693,21 @@ var ReactDOMSelect = ReactCompositeCompo
 
     return select(props, this.props.children);
   },
 
   componentDidMount: function() {
     updateOptions(this, LinkedValueUtils.getValue(this));
   },
 
-  componentDidUpdate: function() {
+  componentDidUpdate: function(prevProps) {
     var value = LinkedValueUtils.getValue(this);
-    if (value != null) {
+    var prevMultiple = !!prevProps.multiple;
+    var multiple = !!this.props.multiple;
+    if (value != null || prevMultiple !== multiple) {
       updateOptions(this, value);
     }
   },
 
   _handleChange: function(event) {
     var returnValue;
     var onChange = LinkedValueUtils.getOnChange(this);
     if (onChange) {
@@ -8166,17 +8732,17 @@ var ReactDOMSelect = ReactCompositeCompo
     this.setState({value: selectedValue});
     return returnValue;
   }
 
 });
 
 module.exports = ReactDOMSelect;
 
-},{"./AutoFocusMixin":1,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./invariant":125,"./merge":134}],45:[function(_dereq_,module,exports){
+},{"./AutoFocusMixin":1,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./merge":144}],50:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8187,20 +8753,31 @@ module.exports = ReactDOMSelect;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactDOMSelection
  */
 
 "use strict";
 
+var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
+
 var getNodeForCharacterOffset = _dereq_("./getNodeForCharacterOffset");
 var getTextContentAccessor = _dereq_("./getTextContentAccessor");
 
 /**
+ * While `isCollapsed` is available on the Selection object and `collapsed`
+ * is available on the Range object, IE11 sometimes gets them wrong.
+ * If the anchor/focus nodes and offsets are the same, the range is collapsed.
+ */
+function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
+  return anchorNode === focusNode && anchorOffset === focusOffset;
+}
+
+/**
  * Get the appropriate anchor and focus node/offset pairs for IE.
  *
  * The catch here is that IE's selection API doesn't provide information
  * about whether the selection is forward or backward, so we have to
  * behave as though it's always forward.
  *
  * IE text differs from modern selection in that it behaves as though
  * block elements end with a new line. This means character offsets will
@@ -8240,23 +8817,41 @@ function getModernOffsets(node) {
   }
 
   var anchorNode = selection.anchorNode;
   var anchorOffset = selection.anchorOffset;
   var focusNode = selection.focusNode;
   var focusOffset = selection.focusOffset;
 
   var currentRange = selection.getRangeAt(0);
-  var rangeLength = currentRange.toString().length;
+
+  // If the node and offset values are the same, the selection is collapsed.
+  // `Selection.isCollapsed` is available natively, but IE sometimes gets
+  // this value wrong.
+  var isSelectionCollapsed = isCollapsed(
+    selection.anchorNode,
+    selection.anchorOffset,
+    selection.focusNode,
+    selection.focusOffset
+  );
+
+  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
 
   var tempRange = currentRange.cloneRange();
   tempRange.selectNodeContents(node);
   tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
 
-  var start = tempRange.toString().length;
+  var isTempRangeCollapsed = isCollapsed(
+    tempRange.startContainer,
+    tempRange.startOffset,
+    tempRange.endContainer,
+    tempRange.endOffset
+  );
+
+  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
   var end = start + rangeLength;
 
   // Detect whether the selection is backward.
   var detectionRange = document.createRange();
   detectionRange.setStart(anchorNode, anchorOffset);
   detectionRange.setEnd(focusNode, focusOffset);
   var isBackward = detectionRange.collapsed;
   detectionRange.detach();
@@ -8336,38 +8931,34 @@ function setModernOffsets(node, offsets)
       range.setEnd(endMarker.node, endMarker.offset);
       selection.addRange(range);
     }
 
     range.detach();
   }
 }
 
+var useIEOffsets = ExecutionEnvironment.canUseDOM && document.selection;
+
 var ReactDOMSelection = {
   /**
    * @param {DOMElement} node
    */
-  getOffsets: function(node) {
-    var getOffsets = document.selection ? getIEOffsets : getModernOffsets;
-    return getOffsets(node);
-  },
+  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,
 
   /**
    * @param {DOMElement|DOMTextNode} node
    * @param {object} offsets
    */
-  setOffsets: function(node, offsets) {
-    var setOffsets = document.selection ? setIEOffsets : setModernOffsets;
-    setOffsets(node, offsets);
-  }
+  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
 };
 
 module.exports = ReactDOMSelection;
 
-},{"./getNodeForCharacterOffset":119,"./getTextContentAccessor":121}],46:[function(_dereq_,module,exports){
+},{"./ExecutionEnvironment":22,"./getNodeForCharacterOffset":127,"./getTextContentAccessor":129}],51:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8448,38 +9039,36 @@ var ReactDOMTextarea = ReactCompositeCom
       defaultValue = '';
     }
     var value = LinkedValueUtils.getValue(this);
     return {
       // We save the initial value so that `ReactDOMComponent` doesn't update
       // `textContent` (unnecessary since we update value).
       // The initial value can be a boolean or object so that's why it's
       // forced to be a string.
-      initialValue: '' + (value != null ? value : defaultValue),
-      value: defaultValue
+      initialValue: '' + (value != null ? value : defaultValue)
     };
   },
 
   shouldComponentUpdate: function() {
     // Defer any updates to this component during the `onChange` handler.
     return !this._isChanging;
   },
 
   render: function() {
     // Clone `this.props` so we don't mutate the input.
     var props = merge(this.props);
-    var value = LinkedValueUtils.getValue(this);
 
     ("production" !== "development" ? invariant(
       props.dangerouslySetInnerHTML == null,
       '`dangerouslySetInnerHTML` does not make sense on <textarea>.'
     ) : invariant(props.dangerouslySetInnerHTML == null));
 
     props.defaultValue = null;
-    props.value = value != null ? value : this.state.value;
+    props.value = null;
     props.onChange = this._handleChange;
 
     // Always set children to the same thing. In IE9, the selection range will
     // get reset if `textContent` is mutated.
     return textarea(props, this.state.initialValue);
   },
 
   componentDidUpdate: function(prevProps, prevState, prevContext) {
@@ -8503,17 +9092,17 @@ var ReactDOMTextarea = ReactCompositeCom
     this.setState({value: event.target.value});
     return returnValue;
   }
 
 });
 
 module.exports = ReactDOMTextarea;
 
-},{"./AutoFocusMixin":1,"./DOMPropertyOperations":10,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":27,"./ReactCompositeComponent":33,"./ReactDOM":36,"./invariant":125,"./merge":134,"./warning":148}],47:[function(_dereq_,module,exports){
+},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./invariant":134,"./merge":144,"./warning":158}],52:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8564,33 +9153,33 @@ var transaction = new ReactDefaultBatchi
 
 var ReactDefaultBatchingStrategy = {
   isBatchingUpdates: false,
 
   /**
    * Call the provided function in a context within which calls to `setState`
    * and friends are batched such that components aren't updated unnecessarily.
    */
-  batchedUpdates: function(callback, param) {
+  batchedUpdates: function(callback, a, b) {
     var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
 
     ReactDefaultBatchingStrategy.isBatchingUpdates = true;
 
     // The code is written this way to avoid extra allocations
     if (alreadyBatchingUpdates) {
-      callback(param);
+      callback(a, b);
     } else {
-      transaction.perform(callback, null, param);
+      transaction.perform(callback, null, a, b);
     }
   }
 };
 
 module.exports = ReactDefaultBatchingStrategy;
 
-},{"./ReactUpdates":81,"./Transaction":96,"./emptyFunction":109,"./mixInto":137}],48:[function(_dereq_,module,exports){
+},{"./ReactUpdates":87,"./Transaction":104,"./emptyFunction":116,"./mixInto":147}],53:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8601,53 +9190,51 @@ module.exports = ReactDefaultBatchingStr
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  * @providesModule ReactDefaultInjection
  */
 
 "use strict";
 
-var ReactInjection = _dereq_("./ReactInjection");
-
-var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
-
-var DefaultDOMPropertyConfig = _dereq_("./DefaultDOMPropertyConfig");
-
+var BeforeInputEventPlugin = _dereq_("./BeforeInputEventPlugin");
 var ChangeEventPlugin = _dereq_("./ChangeEventPlugin");
 var ClientReactRootIndex = _dereq_("./ClientReactRootIndex");
 var CompositionEventPlugin = _dereq_("./CompositionEventPlugin");
 var DefaultEventPluginOrder = _dereq_("./DefaultEventPluginOrder");
 var EnterLeaveEventPlugin = _dereq_("./EnterLeaveEventPlugin");
+var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
+var HTMLDOMPropertyConfig = _dereq_("./HTMLDOMPropertyConfig");
 var MobileSafariClickEventPlugin = _dereq_("./MobileSafariClickEventPlugin");
 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
 var ReactComponentBrowserEnvironment =
   _dereq_("./ReactComponentBrowserEnvironment");
-var ReactEventTopLevelCallback = _dereq_("./ReactEventTopLevelCallback");
+var ReactDefaultBatchingStrategy = _dereq_("./ReactDefaultBatchingStrategy");
 var ReactDOM = _dereq_("./ReactDOM");
 var ReactDOMButton = _dereq_("./ReactDOMButton");
 var ReactDOMForm = _dereq_("./ReactDOMForm");
 var ReactDOMImg = _dereq_("./ReactDOMImg");
 var ReactDOMInput = _dereq_("./ReactDOMInput");
 var ReactDOMOption = _dereq_("./ReactDOMOption");
 var ReactDOMSelect = _dereq_("./ReactDOMSelect");
 var ReactDOMTextarea = _dereq_("./ReactDOMTextarea");
+var ReactEventListener = _dereq_("./ReactEventListener");
+var ReactInjection = _dereq_("./ReactInjection");
 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
 var ReactMount = _dereq_("./ReactMount");
 var SelectEventPlugin = _dereq_("./SelectEventPlugin");
 var ServerReactRootIndex = _dereq_("./ServerReactRootIndex");
 var SimpleEventPlugin = _dereq_("./SimpleEventPlugin");
-
-var ReactDefaultBatchingStrategy = _dereq_("./ReactDefaultBatchingStrategy");
+var SVGDOMPropertyConfig = _dereq_("./SVGDOMPropertyConfig");
 
 var createFullPageComponent = _dereq_("./createFullPageComponent");
 
 function inject() {
-  ReactInjection.EventEmitter.injectTopLevelCallbackCreator(
-    ReactEventTopLevelCallback
+  ReactInjection.EventEmitter.injectReactEventListener(
+    ReactEventListener
   );
 
   /**
    * Inject modules for resolving DOM hierarchy and plugin ordering.
    */
   ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);
   ReactInjection.EventPluginHub.injectInstanceHandle(ReactInstanceHandles);
   ReactInjection.EventPluginHub.injectMount(ReactMount);
@@ -8657,41 +9244,46 @@ function inject() {
    * them).
    */
   ReactInjection.EventPluginHub.injectEventPluginsByName({
     SimpleEventPlugin: SimpleEventPlugin,
     EnterLeaveEventPlugin: EnterLeaveEventPlugin,
     ChangeEventPlugin: ChangeEventPlugin,
     CompositionEventPlugin: CompositionEventPlugin,
     MobileSafariClickEventPlugin: MobileSafariClickEventPlugin,
-    SelectEventPlugin: SelectEventPlugin
+    SelectEventPlugin: SelectEventPlugin,
+    BeforeInputEventPlugin: BeforeInputEventPlugin
   });
 
   ReactInjection.DOM.injectComponentClasses({
     button: ReactDOMButton,
     form: ReactDOMForm,
     img: ReactDOMImg,
     input: ReactDOMInput,
     option: ReactDOMOption,
     select: ReactDOMSelect,
     textarea: ReactDOMTextarea,
 
     html: createFullPageComponent(ReactDOM.html),
     head: createFullPageComponent(ReactDOM.head),
-    title: createFullPageComponent(ReactDOM.title),
     body: createFullPageComponent(ReactDOM.body)
   });
 
-
   // This needs to happen after createFullPageComponent() otherwise the mixin
   // gets double injected.
   ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin);
 
-  ReactInjection.DOMProperty.injectDOMPropertyConfig(DefaultDOMPropertyConfig);
-
+  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
+  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);
+
+  ReactInjection.EmptyComponent.injectEmptyComponent(ReactDOM.noscript);
+
+  ReactInjection.Updates.injectReconcileTransaction(
+    ReactComponentBrowserEnvironment.ReactReconcileTransaction
+  );
   ReactInjection.Updates.injectBatchingStrategy(
     ReactDefaultBatchingStrategy
   );
 
   ReactInjection.RootIndex.injectCreateReactRootIndex(
     ExecutionEnvironment.canUseDOM ?
       ClientReactRootIndex.createReactRootIndex :
       ServerReactRootIndex.createReactRootIndex
@@ -8707,17 +9299,17 @@ function inject() {
     }
   }
 }
 
 module.exports = {
   inject: inject
 };
 
-},{"./ChangeEventPlugin":5,"./ClientReactRootIndex":6,"./CompositionEventPlugin":7,"./DefaultDOMPropertyConfig":12,"./DefaultEventPluginOrder":13,"./EnterLeaveEventPlugin":14,"./ExecutionEnvironment":21,"./MobileSafariClickEventPlugin":24,"./ReactBrowserComponentMixin":27,"./ReactComponentBrowserEnvironment":32,"./ReactDOM":36,"./ReactDOMButton":37,"./ReactDOMForm":39,"./ReactDOMImg":41,"./ReactDOMInput":42,"./ReactDOMOption":43,"./ReactDOMSelect":44,"./ReactDOMTextarea":46,"./ReactDefaultBatchingStrategy":47,"./ReactDefaultPerf":49,"./ReactEventTopLevelCallback":54,"./ReactInjection":55,"./ReactInstanceHandles":57,"./ReactMount":60,"./SelectEventPlugin":83,"./ServerReactRootIndex":84,"./SimpleEventPlugin":85,"./createFullPageComponent":104}],49:[function(_dereq_,module,exports){
+},{"./BeforeInputEventPlugin":2,"./ChangeEventPlugin":7,"./ClientReactRootIndex":8,"./CompositionEventPlugin":9,"./DefaultEventPluginOrder":14,"./EnterLeaveEventPlugin":15,"./ExecutionEnvironment":22,"./HTMLDOMPropertyConfig":23,"./MobileSafariClickEventPlugin":27,"./ReactBrowserComponentMixin":30,"./ReactComponentBrowserEnvironment":36,"./ReactDOM":41,"./ReactDOMButton":42,"./ReactDOMForm":44,"./ReactDOMImg":46,"./ReactDOMInput":47,"./ReactDOMOption":48,"./ReactDOMSelect":49,"./ReactDOMTextarea":51,"./ReactDefaultBatchingStrategy":52,"./ReactDefaultPerf":54,"./ReactEventListener":61,"./ReactInjection":62,"./ReactInstanceHandles":64,"./ReactMount":67,"./SVGDOMPropertyConfig":89,"./SelectEventPlugin":90,"./ServerReactRootIndex":91,"./SimpleEventPlugin":92,"./createFullPageComponent":112}],54:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -8740,18 +9332,23 @@ var ReactMount = _dereq_("./ReactMount")
 var ReactPerf = _dereq_("./ReactPerf");
 
 var performanceNow = _dereq_("./performanceNow");
 
 function roundFloat(val) {
   return Math.floor(val * 100) / 100;
 }
 
+function addValue(obj, key, val) {
+  obj[key] = (obj[key] || 0) + val;
+}
+
 var ReactDefaultPerf = {
   _allMeasurements: [], // last item in the list is the current one
+  _mountStack: [0],
   _injected: false,
 
   start: function() {
     if (!ReactDefaultPerf._injected) {
       ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);
     }
 
     ReactDefaultPerf._allMeasurements.length = 0;
@@ -8768,25 +9365,25 @@ var ReactDefaultPerf = {
 
   printExclusive: function(measurements) {
     measurements = measurements || ReactDefaultPerf._allMeasurements;
     var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements);
     console.table(summary.map(function(item) {
       return {
         'Component class name': item.componentName,
         'Total inclusive time (ms)': roundFloat(item.inclusive),
-        'Total exclusive time (ms)': roundFloat(item.exclusive),
-        'Exclusive time per instance (ms)': roundFloat(item.exclusive / item.count),
+        'Exclusive mount time (ms)': roundFloat(item.exclusive),
+        'Exclusive render time (ms)': roundFloat(item.render),
+        'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),
+        'Render time per instance (ms)': roundFloat(item.render / item.count),
         'Instances': item.count
       };
     }));
-    console.log(
-      'Total time:',
-      ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
-    );
+    // TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct
+    // number.
   },
 
   printInclusive: function(measurements) {
     measurements = measurements || ReactDefaultPerf._allMeasurements;
     var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements);
     console.table(summary.map(function(item) {
       return {
         'Owner > component': item.componentName,
@@ -8859,16 +9456,17 @@ var ReactDefaultPerf = {
           fnName === 'flushBatchedUpdates') {
         // A "measurement" is a set of metrics recorded for each flush. We want
         // to group the metrics for a given flush together so we can look at the
         // components that rendered and the DOM operations that actually
         // happened to determine the amount of "wasted work" performed.
         ReactDefaultPerf._allMeasurements.push({
           exclusive: {},
           inclusive: {},
+          render: {},
           counts: {},
           writes: {},
           displayNames: {},
           totalTime: 0
         });
         start = performanceNow();
         rv = func.apply(this, args);
         ReactDefaultPerf._allMeasurements[
@@ -8921,49 +9519,60 @@ var ReactDefaultPerf = {
         fnName === 'mountComponent' ||
         fnName === 'updateComponent' || // TODO: receiveComponent()?
         fnName === '_renderValidatedComponent')) {
 
         var rootNodeID = fnName === 'mountComponent' ?
           args[0] :
           this._rootNodeID;
         var isRender = fnName === '_renderValidatedComponent';
+        var isMount = fnName === 'mountComponent';
+
+        var mountStack = ReactDefaultPerf._mountStack;
         var entry = ReactDefaultPerf._allMeasurements[
           ReactDefaultPerf._allMeasurements.length - 1
         ];
 
         if (isRender) {
-          entry.counts[rootNodeID] = entry.counts[rootNodeID] || 0;
-          entry.counts[rootNodeID] += 1;
+          addValue(entry.counts, rootNodeID, 1);
+        } else if (isMount) {
+          mountStack.push(0);
         }
 
         start = performanceNow();
         rv = func.apply(this, args);
         totalTime = performanceNow() - start;
 
-        var typeOfLog = isRender ? entry.exclusive : entry.inclusive;
-        typeOfLog[rootNodeID] = typeOfLog[rootNodeID] || 0;
-        typeOfLog[rootNodeID] += totalTime;
+        if (isRender) {
+          addValue(entry.render, rootNodeID, totalTime);
+        } else if (isMount) {
+          var subMountTime = mountStack.pop();
+          mountStack[mountStack.length - 1] += totalTime;
+          addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);
+          addValue(entry.inclusive, rootNodeID, totalTime);
+        } else {
+          addValue(entry.inclusive, rootNodeID, totalTime);
+        }
 
         entry.displayNames[rootNodeID] = {
           current: this.constructor.displayName,
           owner: this._owner ? this._owner.constructor.displayName : '<root>'
         };
 
         return rv;
       } else {
         return func.apply(this, args);
       }
     };
   }
 };
 
 module.exports = ReactDefaultPerf;
 
-},{"./DOMProperty":9,"./ReactDefaultPerfAnalysis":50,"./ReactMount":60,"./ReactPerf":65,"./performanceNow":142}],50:[function(_dereq_,module,exports){
+},{"./DOMProperty":11,"./ReactDefaultPerfAnalysis":55,"./ReactMount":67,"./ReactPerf":71,"./performanceNow":151}],55:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -9036,18 +9645,22 @@ function getExclusiveSummary(measurement
 
     for (var id in allIDs) {
       displayName = measurement.displayNames[id].current;
 
       candidates[displayName] = candidates[displayName] || {
         componentName: displayName,
         inclusive: 0,
         exclusive: 0,
+        render: 0,
         count: 0
       };
+      if (measurement.render[id]) {
+        candidates[displayName].render += measurement.render[id];
+      }
       if (measurement.exclusive[id]) {
         candidates[displayName].exclusive += measurement.exclusive[id];
       }
       if (measurement.inclusive[id]) {
         candidates[displayName].inclusive += measurement.inclusive[id];
       }
       if (measurement.counts[id]) {
         candidates[displayName].count += measurement.counts[id];
@@ -9154,17 +9767,635 @@ var ReactDefaultPerfAnalysis = {
   getExclusiveSummary: getExclusiveSummary,
   getInclusiveSummary: getInclusiveSummary,
   getDOMSummary: getDOMSummary,
   getTotalTime: getTotalTime
 };
 
 module.exports = ReactDefaultPerfAnalysis;
 
-},{"./merge":134}],51:[function(_dereq_,module,exports){
+},{"./merge":144}],56:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ReactDescriptor
+ */
+
+"use strict";
+
+var ReactContext = _dereq_("./ReactContext");
+var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+
+var merge = _dereq_("./merge");
+var warning = _dereq_("./warning");
+
+/**
+ * Warn for mutations.
+ *
+ * @internal
+ * @param {object} object
+ * @param {string} key
+ */
+function defineWarningProperty(object, key) {
+  Object.defineProperty(object, key, {
+
+    configurable: false,
+    enumerable: true,
+
+    get: function() {
+      if (!this._store) {
+        return null;
+      }
+      return this._store[key];
+    },
+
+    set: function(value) {
+      ("production" !== "development" ? warning(
+        false,
+        'Don\'t set the ' + key + ' property of the component. ' +
+        'Mutate the existing props object instead.'
+      ) : null);
+      this._store[key] = value;
+    }
+
+  });
+}
+
+/**
+ * This is updated to true if the membrane is successfully created.
+ */
+var useMutationMembrane = false;
+
+/**
+ * Warn for mutations.
+ *
+ * @internal
+ * @param {object} descriptor
+ */
+function defineMutationMembrane(prototype) {
+  try {
+    var pseudoFrozenProperties = {
+      props: true
+    };
+    for (var key in pseudoFrozenProperties) {
+      defineWarningProperty(prototype, key);
+    }
+    useMutationMembrane = true;
+  } catch (x) {
+    // IE will fail on defineProperty
+  }
+}
+
+/**
+ * Transfer static properties from the source to the target. Functions are
+ * rebound to have this reflect the original source.
+ */
+function proxyStaticMethods(target, source) {
+  if (typeof source !== 'function') {
+    return;
+  }
+  for (var key in source) {
+    if (source.hasOwnProperty(key)) {
+      var value = source[key];
+      if (typeof value === 'function') {
+        var bound = value.bind(source);
+        // Copy any properties defined on the function, such as `isRequired` on
+        // a PropTypes validator. (mergeInto refuses to work on functions.)
+        for (var k in value) {
+          if (value.hasOwnProperty(k)) {
+            bound[k] = value[k];
+          }
+        }
+        target[key] = bound;
+      } else {
+        target[key] = value;
+      }
+    }
+  }
+}
+
+/**
+ * Base constructor for all React descriptors. This is only used to make this
+ * work with a dynamic instanceof check. Nothing should live on this prototype.
+ *
+ * @param {*} type
+ * @internal
+ */
+var ReactDescriptor = function() {};
+
+if ("production" !== "development") {
+  defineMutationMembrane(ReactDescriptor.prototype);
+}
+
+ReactDescriptor.createFactory = function(type) {
+
+  var descriptorPrototype = Object.create(ReactDescriptor.prototype);
+
+  var factory = function(props, children) {
+    // For consistency we currently allocate a new object for every descriptor.
+    // This protects the descriptor from being mutated by the original props
+    // object being mutated. It also protects the original props object from
+    // being mutated by children arguments and default props. This behavior
+    // comes with a performance cost and could be deprecated in the future.
+    // It could also be optimized with a smarter JSX transform.
+    if (props == null) {
+      props = {};
+    } else if (typeof props === 'object') {
+      props = merge(props);
+    }
+
+    // Children can be more than one argument, and those are transferred onto
+    // the newly allocated props object.
+    var childrenLength = arguments.length - 1;
+    if (childrenLength === 1) {
+      props.children = children;
+    } else if (childrenLength > 1) {
+      var childArray = Array(childrenLength);
+      for (var i = 0; i < childrenLength; i++) {
+        childArray[i] = arguments[i + 1];
+      }
+      props.children = childArray;
+    }
+
+    // Initialize the descriptor object
+    var descriptor = Object.create(descriptorPrototype);
+
+    // Record the component responsible for creating this descriptor.
+    descriptor._owner = ReactCurrentOwner.current;
+
+    // TODO: Deprecate withContext, and then the context becomes accessible
+    // through the owner.
+    descriptor._context = ReactContext.current;
+
+    if ("production" !== "development") {
+      // The validation flag and props are currently mutative. We put them on
+      // an external backing store so that we can freeze the whole object.
+      // This can be replaced with a WeakMap once they are implemented in
+      // commonly used development environments.
+      descriptor._store = { validated: false, props: props };
+
+      // We're not allowed to set props directly on the object so we early
+      // return and rely on the prototype membrane to forward to the backing
+      // store.
+      if (useMutationMembrane) {
+        Object.freeze(descriptor);
+        return descriptor;
+      }
+    }
+
+    descriptor.props = props;
+    return descriptor;
+  };
+
+  // Currently we expose the prototype of the descriptor so that
+  // <Foo /> instanceof Foo works. This is controversial pattern.
+  factory.prototype = descriptorPrototype;
+
+  // Expose the type on the factory and the prototype so that it can be
+  // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
+  // static methods like <Foo />.type.staticMethod();
+  // This should not be named constructor since this may not be the function
+  // that created the descriptor, and it may not even be a constructor.
+  factory.type = type;
+  descriptorPrototype.type = type;
+
+  proxyStaticMethods(factory, type);
+
+  // Expose a unique constructor on the prototype is that this works with type
+  // systems that compare constructor properties: <Foo />.constructor === Foo
+  // This may be controversial since it requires a known factory function.
+  descriptorPrototype.constructor = factory;
+
+  return factory;
+
+};
+
+ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) {
+  var newDescriptor = Object.create(oldDescriptor.constructor.prototype);
+  // It's important that this property order matches the hidden class of the
+  // original descriptor to maintain perf.
+  newDescriptor._owner = oldDescriptor._owner;
+  newDescriptor._context = oldDescriptor._context;
+
+  if ("production" !== "development") {
+    newDescriptor._store = {
+      validated: oldDescriptor._store.validated,
+      props: newProps
+    };
+    if (useMutationMembrane) {
+      Object.freeze(newDescriptor);
+      return newDescriptor;
+    }
+  }
+
+  newDescriptor.props = newProps;
+  return newDescriptor;
+};
+
+/**
+ * Checks if a value is a valid descriptor constructor.
+ *
+ * @param {*}
+ * @return {boolean}
+ * @public
+ */
+ReactDescriptor.isValidFactory = function(factory) {
+  return typeof factory === 'function' &&
+         factory.prototype instanceof ReactDescriptor;
+};
+
+/**
+ * @param {?object} object
+ * @return {boolean} True if `object` is a valid component.
+ * @final
+ */
+ReactDescriptor.isValidDescriptor = function(object) {
+  return object instanceof ReactDescriptor;
+};
+
+module.exports = ReactDescriptor;
+
+},{"./ReactContext":39,"./ReactCurrentOwner":40,"./merge":144,"./warning":158}],57:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ReactDescriptorValidator
+ */
+
+/**
+ * ReactDescriptorValidator provides a wrapper around a descriptor factory
+ * which validates the props passed to the descriptor. This is intended to be
+ * used only in DEV and could be replaced by a static type checker for languages
+ * that support it.
+ */
+
+"use strict";
+
+var ReactDescriptor = _dereq_("./ReactDescriptor");
+var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations");
+var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+
+var monitorCodeUse = _dereq_("./monitorCodeUse");
+
+/**
+ * Warn if there's no key explicitly set on dynamic arrays of children or
+ * object keys are not valid. This allows us to keep track of children between
+ * updates.
+ */
+var ownerHasKeyUseWarning = {
+  'react_key_warning': {},
+  'react_numeric_key_warning': {}
+};
+var ownerHasMonitoredObjectMap = {};
+
+var loggedTypeFailures = {};
+
+var NUMERIC_PROPERTY_REGEX = /^\d+$/;
+
+/**
+ * Gets the current owner's displayName for use in warnings.
+ *
+ * @internal
+ * @return {?string} Display name or undefined
+ */
+function getCurrentOwnerDisplayName() {
+  var current = ReactCurrentOwner.current;
+  return current && current.constructor.displayName || undefined;
+}
+
+/**
+ * Warn if the component doesn't have an explicit key assigned to it.
+ * This component is in an array. The array could grow and shrink or be
+ * reordered. All children that haven't already been validated are required to
+ * have a "key" property assigned to it.
+ *
+ * @internal
+ * @param {ReactComponent} component Component that requires a key.
+ * @param {*} parentType component's parent's type.
+ */
+function validateExplicitKey(component, parentType) {
+  if (component._store.validated || component.props.key != null) {
+    return;
+  }
+  component._store.validated = true;
+
+  warnAndMonitorForKeyUse(
+    'react_key_warning',
+    'Each child in an array should have a unique "key" prop.',
+    component,
+    parentType
+  );
+}
+
+/**
+ * Warn if the key is being defined as an object property but has an incorrect
+ * value.
+ *
+ * @internal
+ * @param {string} name Property name of the key.
+ * @param {ReactComponent} component Component that requires a key.
+ * @param {*} parentType component's parent's type.
+ */
+function validatePropertyKey(name, component, parentType) {
+  if (!NUMERIC_PROPERTY_REGEX.test(name)) {
+    return;
+  }
+  warnAndMonitorForKeyUse(
+    'react_numeric_key_warning',
+    'Child objects should have non-numeric keys so ordering is preserved.',
+    component,
+    parentType
+  );
+}
+
+/**
+ * Shared warning and monitoring code for the key warnings.
+ *
+ * @internal
+ * @param {string} warningID The id used when logging.
+ * @param {string} message The base warning that gets output.
+ * @param {ReactComponent} component Component that requires a key.
+ * @param {*} parentType component's parent's type.
+ */
+function warnAndMonitorForKeyUse(warningID, message, component, parentType) {
+  var ownerName = getCurrentOwnerDisplayName();
+  var parentName = parentType.displayName;
+
+  var useName = ownerName || parentName;
+  var memoizer = ownerHasKeyUseWarning[warningID];
+  if (memoizer.hasOwnProperty(useName)) {
+    return;
+  }
+  memoizer[useName] = true;
+
+  message += ownerName ?
+    (" Check the render method of " + ownerName + ".") :
+    (" Check the renderComponent call using <" + parentName + ">.");
+
+  // Usually the current owner is the offender, but if it accepts children as a
+  // property, it may be the creator of the child that's responsible for
+  // assigning it a key.
+  var childOwnerName = null;
+  if (component._owner && component._owner !== ReactCurrentOwner.current) {
+    // Name of the component that originally created this child.
+    childOwnerName = component._owner.constructor.displayName;
+
+    message += (" It was passed a child from " + childOwnerName + ".");
+  }
+
+  message += ' See http://fb.me/react-warning-keys for more information.';
+  monitorCodeUse(warningID, {
+    component: useName,
+    componentOwner: childOwnerName
+  });
+  console.warn(message);
+}
+
+/**
+ * Log that we're using an object map. We're considering deprecating this
+ * feature and replace it with proper Map and ImmutableMap data structures.
+ *
+ * @internal
+ */
+function monitorUseOfObjectMap() {
+  var currentName = getCurrentOwnerDisplayName() || '';
+  if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) {
+    return;
+  }
+  ownerHasMonitoredObjectMap[currentName] = true;
+  monitorCodeUse('react_object_map_children');
+}
+
+/**
+ * Ensure that every component either is passed in a static location, in an
+ * array with an explicit keys property defined, or in an object literal
+ * with valid key property.
+ *
+ * @internal
+ * @param {*} component Statically passed child of any type.
+ * @param {*} parentType component's parent's type.
+ * @return {boolean}
+ */
+function validateChildKeys(component, parentType) {
+  if (Array.isArray(component)) {
+    for (var i = 0; i < component.length; i++) {
+      var child = component[i];
+      if (ReactDescriptor.isValidDescriptor(child)) {
+        validateExplicitKey(child, parentType);
+      }
+    }
+  } else if (ReactDescriptor.isValidDescriptor(component)) {
+    // This component was passed in a valid location.
+    component._store.validated = true;
+  } else if (component && typeof component === 'object') {
+    monitorUseOfObjectMap();
+    for (var name in component) {
+      validatePropertyKey(name, component[name], parentType);
+    }
+  }
+}
+
+/**
+ * Assert that the props are valid
+ *
+ * @param {string} componentName Name of the component for error messages.
+ * @param {object} propTypes Map of prop name to a ReactPropType
+ * @param {object} props
+ * @param {string} location e.g. "prop", "context", "child context"
+ * @private
+ */
+function checkPropTypes(componentName, propTypes, props, location) {
+  for (var propName in propTypes) {
+    if (propTypes.hasOwnProperty(propName)) {
+      var error;
+      // Prop type validation may throw. In case they do, we don't want to
+      // fail the render phase where it didn't fail before. So we log it.
+      // After these have been cleaned up, we'll let them throw.
+      try {
+        error = propTypes[propName](props, propName, componentName, location);
+      } catch (ex) {
+        error = ex;
+      }
+      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
+        // Only monitor this failure once because there tends to be a lot of the
+        // same error.
+        loggedTypeFailures[error.message] = true;
+        // This will soon use the warning module
+        monitorCodeUse(
+          'react_failed_descriptor_type_check',
+          { message: error.message }
+        );
+      }
+    }
+  }
+}
+
+var ReactDescriptorValidator = {
+
+  /**
+   * Wraps a descriptor factory function in another function which validates
+   * the props and context of the descriptor and warns about any failed type
+   * checks.
+   *
+   * @param {function} factory The original descriptor factory
+   * @param {object?} propTypes A prop type definition set
+   * @param {object?} contextTypes A context type definition set
+   * @return {object} The component descriptor, which may be invalid.
+   * @private
+   */
+  createFactory: function(factory, propTypes, contextTypes) {
+    var validatedFactory = function(props, children) {
+      var descriptor = factory.apply(this, arguments);
+
+      for (var i = 1; i < arguments.length; i++) {
+        validateChildKeys(arguments[i], descriptor.type);
+      }
+
+      var name = descriptor.type.displayName;
+      if (propTypes) {
+        checkPropTypes(
+          name,
+          propTypes,
+          descriptor.props,
+          ReactPropTypeLocations.prop
+        );
+      }
+      if (contextTypes) {
+        checkPropTypes(
+          name,
+          contextTypes,
+          descriptor._context,
+          ReactPropTypeLocations.context
+        );
+      }
+      return descriptor;
+    };
+
+    validatedFactory.prototype = factory.prototype;
+    validatedFactory.type = factory.type;
+
+    // Copy static properties
+    for (var key in factory) {
+      if (factory.hasOwnProperty(key)) {
+        validatedFactory[key] = factory[key];
+      }
+    }
+
+    return validatedFactory;
+  }
+
+};
+
+module.exports = ReactDescriptorValidator;
+
+},{"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactPropTypeLocations":74,"./monitorCodeUse":148}],58:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ReactEmptyComponent
+ */
+
+"use strict";
+
+var invariant = _dereq_("./invariant");
+
+var component;
+// This registry keeps track of the React IDs of the components that rendered to
+// `null` (in reality a placeholder such as `noscript`)
+var nullComponentIdsRegistry = {};
+
+var ReactEmptyComponentInjection = {
+  injectEmptyComponent: function(emptyComponent) {
+    component = emptyComponent;
+  }
+};
+
+/**
+ * @return {ReactComponent} component The injected empty component.
+ */
+function getEmptyComponent() {
+  ("production" !== "development" ? invariant(
+    component,
+    'Trying to return null from a render, but no null placeholder component ' +
+    'was injected.'
+  ) : invariant(component));
+  return component();
+}
+
+/**
+ * Mark the component as having rendered to null.
+ * @param {string} id Component's `_rootNodeID`.
+ */
+function registerNullComponentID(id) {
+  nullComponentIdsRegistry[id] = true;
+}
+
+/**
+ * Unmark the component as having rendered to null: it renders to something now.
+ * @param {string} id Component's `_rootNodeID`.
+ */
+function deregisterNullComponentID(id) {
+  delete nullComponentIdsRegistry[id];
+}
+
+/**
+ * @param {string} id Component's `_rootNodeID`.
+ * @return {boolean} True if the component is rendered to null.
+ */
+function isNullComponentID(id) {
+  return nullComponentIdsRegistry[id];
+}
+
+var ReactEmptyComponent = {
+  deregisterNullComponentID: deregisterNullComponentID,
+  getEmptyComponent: getEmptyComponent,
+  injection: ReactEmptyComponentInjection,
+  isNullComponentID: isNullComponentID,
+  registerNullComponentID: registerNullComponentID
+};
+
+module.exports = ReactEmptyComponent;
+
+},{"./invariant":134}],59:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -9193,358 +10424,17 @@ var ReactErrorUtils = {
    */
   guard: function(func, name) {
     return func;
   }
 };
 
 module.exports = ReactErrorUtils;
 
-},{}],52:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2014 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @providesModule ReactEventEmitter
- * @typechecks static-only
- */
-
-"use strict";
-
-var EventConstants = _dereq_("./EventConstants");
-var EventListener = _dereq_("./EventListener");
-var EventPluginHub = _dereq_("./EventPluginHub");
-var EventPluginRegistry = _dereq_("./EventPluginRegistry");
-var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
-var ReactEventEmitterMixin = _dereq_("./ReactEventEmitterMixin");
-var ViewportMetrics = _dereq_("./ViewportMetrics");
-
-var invariant = _dereq_("./invariant");
-var isEventSupported = _dereq_("./isEventSupported");
-var merge = _dereq_("./merge");
-
-/**
- * Summary of `ReactEventEmitter` event handling:
- *
- *  - Top-level delegation is used to trap native browser events. We normalize
- *    and de-duplicate events to account for browser quirks.
- *
- *  - Forward these native events (with the associated top-level type used to
- *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want
- *    to extract any synthetic events.
- *
- *  - The `EventPluginHub` will then process each event by annotating them with
- *    "dispatches", a sequence of listeners and IDs that care about that event.
- *
- *  - The `EventPluginHub` then dispatches the events.
- *
- * Overview of React and the event system:
- *
- *                   .
- * +------------+    .
- * |    DOM     |    .
- * +------------+    .                         +-----------+
- *       +           .               +--------+|SimpleEvent|
- *       |           .               |         |Plugin     |
- * +-----|------+    .               v         +-----------+
- * |     |      |    .    +--------------+                    +------------+
- * |     +-----------.--->|EventPluginHub|                    |    Event   |
- * |            |    .    |              |     +-----------+  | Propagators|
- * | ReactEvent |    .    |              |     |TapEvent   |  |------------|
- * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|
- * |            |    .    |              |     +-----------+  |  utilities |
- * |     +-----------.--->|              |                    +------------+
- * |     |      |    .    +--------------+
- * +-----|------+    .                ^        +-----------+
- *       |           .                |        |Enter/Leave|
- *       +           .                +-------+|Plugin     |
- * +-------------+   .                         +-----------+
- * | application |   .
- * |-------------|   .
- * |             |   .
- * |             |   .
- * +-------------+   .
- *                   .
- *    React Core     .  General Purpose Event Plugin System
- */
-
-var alreadyListeningTo = {};
-var isMonitoringScrollValue = false;
-var reactTopListenersCounter = 0;
-
-// For events like 'submit' which don't consistently bubble (which we trap at a
-// lower node than `document`), binding at `document` would cause duplicate
-// events so we don't include them here
-var topEventMapping = {
-  topBlur: 'blur',
-  topChange: 'change',
-  topClick: 'click',
-  topCompositionEnd: 'compositionend',
-  topCompositionStart: 'compositionstart',
-  topCompositionUpdate: 'compositionupdate',
-  topContextMenu: 'contextmenu',
-  topCopy: 'copy',
-  topCut: 'cut',
-  topDoubleClick: 'dblclick',
-  topDrag: 'drag',
-  topDragEnd: 'dragend',
-  topDragEnter: 'dragenter',
-  topDragExit: 'dragexit',
-  topDragLeave: 'dragleave',
-  topDragOver: 'dragover',
-  topDragStart: 'dragstart',
-  topDrop: 'drop',
-  topFocus: 'focus',
-  topInput: 'input',
-  topKeyDown: 'keydown',
-  topKeyPress: 'keypress',
-  topKeyUp: 'keyup',
-  topMouseDown: 'mousedown',
-  topMouseMove: 'mousemove',
-  topMouseOut: 'mouseout',
-  topMouseOver: 'mouseover',
-  topMouseUp: 'mouseup',
-  topPaste: 'paste',
-  topScroll: 'scroll',
-  topSelectionChange: 'selectionchange',
-  topTouchCancel: 'touchcancel',
-  topTouchEnd: 'touchend',
-  topTouchMove: 'touchmove',
-  topTouchStart: 'touchstart',
-  topWheel: 'wheel'
-};
-
-/**
- * To ensure no conflicts with other potential React instances on the page
- */
-var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2);
-
-function getListeningForDocument(mountAt) {
-  if (mountAt[topListenersIDKey] == null) {
-    mountAt[topListenersIDKey] = reactTopListenersCounter++;
-    alreadyListeningTo[mountAt[topListenersIDKey]] = {};
-  }
-  return alreadyListeningTo[mountAt[topListenersIDKey]];
-}
-
-/**
- * Traps top-level events by using event bubbling.
- *
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {string} handlerBaseName Event name (e.g. "click").
- * @param {DOMEventTarget} element Element on which to attach listener.
- * @internal
- */
-function trapBubbledEvent(topLevelType, handlerBaseName, element) {
-  EventListener.listen(
-    element,
-    handlerBaseName,
-    ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback(
-      topLevelType
-    )
-  );
-}
-
-/**
- * Traps a top-level event by using event capturing.
- *
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {string} handlerBaseName Event name (e.g. "click").
- * @param {DOMEventTarget} element Element on which to attach listener.
- * @internal
- */
-function trapCapturedEvent(topLevelType, handlerBaseName, element) {
-  EventListener.capture(
-    element,
-    handlerBaseName,
-    ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback(
-      topLevelType
-    )
-  );
-}
-
-/**
- * `ReactEventEmitter` is used to attach top-level event listeners. For example:
- *
- *   ReactEventEmitter.putListener('myID', 'onClick', myFunction);
- *
- * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
- *
- * @internal
- */
-var ReactEventEmitter = merge(ReactEventEmitterMixin, {
-
-  /**
-   * React references `ReactEventTopLevelCallback` using this property in order
-   * to allow dependency injection.
-   */
-  TopLevelCallbackCreator: null,
-
-  injection: {
-    /**
-     * @param {function} TopLevelCallbackCreator
-     */
-    injectTopLevelCallbackCreator: function(TopLevelCallbackCreator) {
-      ReactEventEmitter.TopLevelCallbackCreator = TopLevelCallbackCreator;
-    }
-  },
-
-  /**
-   * Sets whether or not any created callbacks should be enabled.
-   *
-   * @param {boolean} enabled True if callbacks should be enabled.
-   */
-  setEnabled: function(enabled) {
-    ("production" !== "development" ? invariant(
-      ExecutionEnvironment.canUseDOM,
-      'setEnabled(...): Cannot toggle event listening in a Worker thread. ' +
-      'This is likely a bug in the framework. Please report immediately.'
-    ) : invariant(ExecutionEnvironment.canUseDOM));
-    if (ReactEventEmitter.TopLevelCallbackCreator) {
-      ReactEventEmitter.TopLevelCallbackCreator.setEnabled(enabled);
-    }
-  },
-
-  /**
-   * @return {boolean} True if callbacks are enabled.
-   */
-  isEnabled: function() {
-    return !!(
-      ReactEventEmitter.TopLevelCallbackCreator &&
-      ReactEventEmitter.TopLevelCallbackCreator.isEnabled()
-    );
-  },
-
-  /**
-   * We listen for bubbled touch events on the document object.
-   *
-   * Firefox v8.01 (and possibly others) exhibited strange behavior when
-   * mounting `onmousemove` events at some node that was not the document
-   * element. The symptoms were that if your mouse is not moving over something
-   * contained within that mount point (for example on the background) the
-   * top-level listeners for `onmousemove` won't be called. However, if you
-   * register the `mousemove` on the document object, then it will of course
-   * catch all `mousemove`s. This along with iOS quirks, justifies restricting
-   * top-level listeners to the document object only, at least for these
-   * movement types of events and possibly all events.
-   *
-   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
-   *
-   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
-   * they bubble to document.
-   *
-   * @param {string} registrationName Name of listener (e.g. `onClick`).
-   * @param {DOMDocument} contentDocument Document which owns the container
-   */
-  listenTo: function(registrationName, contentDocument) {
-    var mountAt = contentDocument;
-    var isListening = getListeningForDocument(mountAt);
-    var dependencies = EventPluginRegistry.
-      registrationNameDependencies[registrationName];
-
-    var topLevelTypes = EventConstants.topLevelTypes;
-    for (var i = 0, l = dependencies.length; i < l; i++) {
-      var dependency = dependencies[i];
-      if (!isListening[dependency]) {
-        var topLevelType = topLevelTypes[dependency];
-
-        if (topLevelType === topLevelTypes.topWheel) {
-          if (isEventSupported('wheel')) {
-            trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);
-          } else if (isEventSupported('mousewheel')) {
-            trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);
-          } else {
-            // Firefox needs to capture a different mouse scroll event.
-            // @see http://www.quirksmode.org/dom/events/tests/scroll.html
-            trapBubbledEvent(
-              topLevelTypes.topWheel,
-              'DOMMouseScroll',
-              mountAt);
-          }
-        } else if (topLevelType === topLevelTypes.topScroll) {
-
-          if (isEventSupported('scroll', true)) {
-            trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);
-          } else {
-            trapBubbledEvent(topLevelTypes.topScroll, 'scroll', window);
-          }
-        } else if (topLevelType === topLevelTypes.topFocus ||
-            topLevelType === topLevelTypes.topBlur) {
-
-          if (isEventSupported('focus', true)) {
-            trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);
-            trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);
-          } else if (isEventSupported('focusin')) {
-            // IE has `focusin` and `focusout` events which bubble.
-            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
-            trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);
-            trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);
-          }
-
-          // to make sure blur and focus event listeners are only attached once
-          isListening[topLevelTypes.topBlur] = true;
-          isListening[topLevelTypes.topFocus] = true;
-        } else if (topEventMapping[dependency]) {
-          trapBubbledEvent(topLevelType, topEventMapping[dependency], mountAt);
-        }
-
-        isListening[dependency] = true;
-      }
-    }
-  },
-
-  /**
-   * Listens to window scroll and resize events. We cache scroll values so that
-   * application code can access them without triggering reflows.
-   *
-   * NOTE: Scroll events do not bubble.
-   *
-   * @see http://www.quirksmode.org/dom/events/scroll.html
-   */
-  ensureScrollValueMonitoring: function(){
-    if (!isMonitoringScrollValue) {
-      var refresh = ViewportMetrics.refreshScrollValues;
-      EventListener.listen(window, 'scroll', refresh);
-      EventListener.listen(window, 'resize', refresh);
-      isMonitoringScrollValue = true;
-    }
-  },
-
-  eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs,
-
-  registrationNameModules: EventPluginHub.registrationNameModules,
-
-  putListener: EventPluginHub.putListener,
-
-  getListener: EventPluginHub.getListener,
-
-  deleteListener: EventPluginHub.deleteListener,
-
-  deleteAllListeners: EventPluginHub.deleteAllListeners,
-
-  trapBubbledEvent: trapBubbledEvent,
-
-  trapCapturedEvent: trapCapturedEvent
-
-});
-
-module.exports = ReactEventEmitter;
-
-},{"./EventConstants":15,"./EventListener":16,"./EventPluginHub":17,"./EventPluginRegistry":18,"./ExecutionEnvironment":21,"./ReactEventEmitterMixin":53,"./ViewportMetrics":97,"./invariant":125,"./isEventSupported":126,"./merge":134}],53:[function(_dereq_,module,exports){
+},{}],60:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -9556,17 +10446,16 @@ module.exports = ReactEventEmitter;
  * limitations under the License.
  *
  * @providesModule ReactEventEmitterMixin
  */
 
 "use strict";
 
 var EventPluginHub = _dereq_("./EventPluginHub");
-var ReactUpdates = _dereq_("./ReactUpdates");
 
 function runEventQueueInBatch(events) {
   EventPluginHub.enqueueEvents(events);
   EventPluginHub.processEventQueue();
 }
 
 var ReactEventEmitterMixin = {
 
@@ -9586,60 +10475,56 @@ var ReactEventEmitterMixin = {
       nativeEvent) {
     var events = EventPluginHub.extractEvents(
       topLevelType,
       topLevelTarget,
       topLevelTargetID,
       nativeEvent
     );
 
-    // Event queue being processed in the same cycle allows `preventDefault`.
-    ReactUpdates.batchedUpdates(runEventQueueInBatch, events);
+    runEventQueueInBatch(events);
   }
 };
 
 module.exports = ReactEventEmitterMixin;
 
-},{"./EventPluginHub":17,"./ReactUpdates":81}],54:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2014 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @providesModule ReactEventTopLevelCallback
+},{"./EventPluginHub":18}],61:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ReactEventListener
  * @typechecks static-only
  */
 
 "use strict";
 
+var EventListener = _dereq_("./EventListener");
+var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
 var PooledClass = _dereq_("./PooledClass");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
 var ReactMount = _dereq_("./ReactMount");
+var ReactUpdates = _dereq_("./ReactUpdates");
 
 var getEventTarget = _dereq_("./getEventTarget");
+var getUnboundedScrollPosition = _dereq_("./getUnboundedScrollPosition");
 var mixInto = _dereq_("./mixInto");
 
 /**
- * @type {boolean}
- * @private
- */
-var _topLevelListenersEnabled = true;
-
-/**
  * Finds the parent React component of `node`.
  *
  * @param {*} node
  * @return {?DOMEventTarget} Parent container, or `null` if the specified node
  *                           is not nested.
  */
 function findParent(node) {
   // TODO: It may be a good idea to cache this to prevent unnecessary DOM
@@ -9647,114 +10532,157 @@ function findParent(node) {
   // mutation observer to listen for all DOM changes.
   var nodeID = ReactMount.getID(node);
   var rootID = ReactInstanceHandles.getReactRootIDFromNodeID(nodeID);
   var container = ReactMount.findReactContainerForID(rootID);
   var parent = ReactMount.getFirstReactDOM(container);
   return parent;
 }
 
-/**
- * Calls ReactEventEmitter.handleTopLevel for each node stored in bookKeeping's
- * ancestor list. Separated from createTopLevelCallback to avoid try/finally
- * deoptimization.
- *
- * @param {string} topLevelType
- * @param {DOMEvent} nativeEvent
- * @param {TopLevelCallbackBookKeeping} bookKeeping
- */
-function handleTopLevelImpl(topLevelType, nativeEvent, bookKeeping) {
+// Used to store ancestor hierarchy in top level callback
+function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
+  this.topLevelType = topLevelType;
+  this.nativeEvent = nativeEvent;
+  this.ancestors = [];
+}
+mixInto(TopLevelCallbackBookKeeping, {
+  destructor: function() {
+    this.topLevelType = null;
+    this.nativeEvent = null;
+    this.ancestors.length = 0;
+  }
+});
+PooledClass.addPoolingTo(
+  TopLevelCallbackBookKeeping,
+  PooledClass.twoArgumentPooler
+);
+
+function handleTopLevelImpl(bookKeeping) {
   var topLevelTarget = ReactMount.getFirstReactDOM(
-    getEventTarget(nativeEvent)
+    getEventTarget(bookKeeping.nativeEvent)
   ) || window;
 
   // Loop through the hierarchy, in case there's any nested components.
   // It's important that we build the array of ancestors before calling any
   // event handlers, because event handlers can modify the DOM, leading to
   // inconsistencies with ReactMount's node cache. See #1105.
   var ancestor = topLevelTarget;
   while (ancestor) {
     bookKeeping.ancestors.push(ancestor);
     ancestor = findParent(ancestor);
   }
 
   for (var i = 0, l = bookKeeping.ancestors.length; i < l; i++) {
     topLevelTarget = bookKeeping.ancestors[i];
     var topLevelTargetID = ReactMount.getID(topLevelTarget) || '';
-    ReactEventEmitter.handleTopLevel(
-      topLevelType,
+    ReactEventListener._handleTopLevel(
+      bookKeeping.topLevelType,
       topLevelTarget,
       topLevelTargetID,
-      nativeEvent
-    );
-  }
-}
-
-// Used to store ancestor hierarchy in top level callback
-function TopLevelCallbackBookKeeping() {
-  this.ancestors = [];
-}
-mixInto(TopLevelCallbackBookKeeping, {
-  destructor: function() {
-    this.ancestors.length = 0;
-  }
-});
-PooledClass.addPoolingTo(TopLevelCallbackBookKeeping);
-
-/**
- * Top-level callback creator used to implement event handling using delegation.
- * This is used via dependency injection.
- */
-var ReactEventTopLevelCallback = {
-
-  /**
-   * Sets whether or not any created callbacks should be enabled.
-   *
-   * @param {boolean} enabled True if callbacks should be enabled.
-   */
+      bookKeeping.nativeEvent
+    );
+  }
+}
+
+function scrollValueMonitor(cb) {
+  var scrollPosition = getUnboundedScrollPosition(window);
+  cb(scrollPosition);
+}
+
+var ReactEventListener = {
+  _enabled: true,
+  _handleTopLevel: null,
+
+  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,
+
+  setHandleTopLevel: function(handleTopLevel) {
+    ReactEventListener._handleTopLevel = handleTopLevel;
+  },
+
   setEnabled: function(enabled) {
-    _topLevelListenersEnabled = !!enabled;
-  },
-
-  /**
-   * @return {boolean} True if callbacks are enabled.
-   */
+    ReactEventListener._enabled = !!enabled;
+  },
+
   isEnabled: function() {
-    return _topLevelListenersEnabled;
-  },
-
-  /**
-   * Creates a callback for the supplied `topLevelType` that could be added as
-   * a listener to the document. The callback computes a `topLevelTarget` which
-   * should be the root node of a mounted React component where the listener
-   * is attached.
+    return ReactEventListener._enabled;
+  },
+
+
+  /**
+   * Traps top-level events by using event bubbling.
    *
    * @param {string} topLevelType Record from `EventConstants`.
-   * @return {function} Callback for handling top-level events.
-   */
-  createTopLevelCallback: function(topLevelType) {
-    return function(nativeEvent) {
-      if (!_topLevelListenersEnabled) {
-        return;
-      }
-
-      var bookKeeping = TopLevelCallbackBookKeeping.getPooled();
-      try {
-        handleTopLevelImpl(topLevelType, nativeEvent, bookKeeping);
-      } finally {
-        TopLevelCallbackBookKeeping.release(bookKeeping);
-      }
-    };
-  }
-
-};
-
-module.exports = ReactEventTopLevelCallback;
-
-},{"./PooledClass":25,"./ReactEventEmitter":52,"./ReactInstanceHandles":57,"./ReactMount":60,"./getEventTarget":117,"./mixInto":137}],55:[function(_dereq_,module,exports){
+   * @param {string} handlerBaseName Event name (e.g. "click").
+   * @param {object} handle Element on which to attach listener.
+   * @return {object} An object with a remove function which will forcefully
+   *                  remove the listener.
+   * @internal
+   */
+  trapBubbledEvent: function(topLevelType, handlerBaseName, handle) {
+    var element = handle;
+    if (!element) {
+      return;
+    }
+    return EventListener.listen(
+      element,
+      handlerBaseName,
+      ReactEventListener.dispatchEvent.bind(null, topLevelType)
+    );
+  },
+
+  /**
+   * Traps a top-level event by using event capturing.
+   *
+   * @param {string} topLevelType Record from `EventConstants`.
+   * @param {string} handlerBaseName Event name (e.g. "click").
+   * @param {object} handle Element on which to attach listener.
+   * @return {object} An object with a remove function which will forcefully
+   *                  remove the listener.
+   * @internal
+   */
+  trapCapturedEvent: function(topLevelType, handlerBaseName, handle) {
+    var element = handle;
+    if (!element) {
+      return;
+    }
+    return EventListener.capture(
+      element,
+      handlerBaseName,
+      ReactEventListener.dispatchEvent.bind(null, topLevelType)
+    );
+  },
+
+  monitorScrollValue: function(refresh) {
+    var callback = scrollValueMonitor.bind(null, refresh);
+    EventListener.listen(window, 'scroll', callback);
+    EventListener.listen(window, 'resize', callback);
+  },
+
+  dispatchEvent: function(topLevelType, nativeEvent) {
+    if (!ReactEventListener._enabled) {
+      return;
+    }
+
+    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(
+      topLevelType,
+      nativeEvent
+    );
+    try {
+      // Event queue being processed in the same cycle allows
+      // `preventDefault`.
+      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
+    } finally {
+      TopLevelCallbackBookKeeping.release(bookKeeping);
+    }
+  }
+};
+
+module.exports = ReactEventListener;
+
+},{"./EventListener":17,"./ExecutionEnvironment":22,"./PooledClass":28,"./ReactInstanceHandles":64,"./ReactMount":67,"./ReactUpdates":87,"./getEventTarget":125,"./getUnboundedScrollPosition":130,"./mixInto":147}],62:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -9770,36 +10698,38 @@ module.exports = ReactEventTopLevelCallb
 
 "use strict";
 
 var DOMProperty = _dereq_("./DOMProperty");
 var EventPluginHub = _dereq_("./EventPluginHub");
 var ReactComponent = _dereq_("./ReactComponent");
 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
 var ReactDOM = _dereq_("./ReactDOM");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
+var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
+var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
 var ReactPerf = _dereq_("./ReactPerf");
 var ReactRootIndex = _dereq_("./ReactRootIndex");
 var ReactUpdates = _dereq_("./ReactUpdates");
 
 var ReactInjection = {
   Component: ReactComponent.injection,
   CompositeComponent: ReactCompositeComponent.injection,
   DOMProperty: DOMProperty.injection,
+  EmptyComponent: ReactEmptyComponent.injection,
   EventPluginHub: EventPluginHub.injection,
   DOM: ReactDOM.injection,
-  EventEmitter: ReactEventEmitter.injection,
+  EventEmitter: ReactBrowserEventEmitter.injection,
   Perf: ReactPerf.injection,
   RootIndex: ReactRootIndex.injection,
   Updates: ReactUpdates.injection
 };
 
 module.exports = ReactInjection;
 
-},{"./DOMProperty":9,"./EventPluginHub":17,"./ReactComponent":31,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactEventEmitter":52,"./ReactPerf":65,"./ReactRootIndex":72,"./ReactUpdates":81}],56:[function(_dereq_,module,exports){
+},{"./DOMProperty":11,"./EventPluginHub":18,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactEmptyComponent":58,"./ReactPerf":71,"./ReactRootIndex":78,"./ReactUpdates":87}],63:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -9932,17 +10862,17 @@ var ReactInputSelection = {
     } else {
       ReactDOMSelection.setOffsets(input, offsets);
     }
   }
 };
 
 module.exports = ReactInputSelection;
 
-},{"./ReactDOMSelection":45,"./containsNode":101,"./focusNode":113,"./getActiveElement":115}],57:[function(_dereq_,module,exports){
+},{"./ReactDOMSelection":50,"./containsNode":109,"./focusNode":120,"./getActiveElement":122}],64:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -10272,17 +11202,17 @@ var ReactInstanceHandles = {
   isAncestorIDOf: isAncestorIDOf,
 
   SEPARATOR: SEPARATOR
 
 };
 
 module.exports = ReactInstanceHandles;
 
-},{"./ReactRootIndex":72,"./invariant":125}],58:[function(_dereq_,module,exports){
+},{"./ReactRootIndex":78,"./invariant":134}],65:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -10317,28 +11247,52 @@ module.exports = ReactInstanceHandles;
  *     this.setState({value: newValue});
  *   }
  * });
  *
  * We have provided some sugary mixins to make the creation and
  * consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin.
  */
 
+var React = _dereq_("./React");
+
 /**
  * @param {*} value current value of the link
  * @param {function} requestChange callback to request a change
  */
 function ReactLink(value, requestChange) {
   this.value = value;
   this.requestChange = requestChange;
 }
 
+/**
+ * Creates a PropType that enforces the ReactLink API and optionally checks the
+ * type of the value being passed inside the link. Example:
+ *
+ * MyComponent.propTypes = {
+ *   tabIndexLink: ReactLink.PropTypes.link(React.PropTypes.number)
+ * }
+ */
+function createLinkTypeChecker(linkType) {
+  var shapes = {
+    value: typeof linkType === 'undefined' ?
+      React.PropTypes.any.isRequired :
+      linkType.isRequired,
+    requestChange: React.PropTypes.func.isRequired
+  };
+  return React.PropTypes.shape(shapes);
+}
+
+ReactLink.PropTypes = {
+  link: createLinkTypeChecker
+};
+
 module.exports = ReactLink;
 
-},{}],59:[function(_dereq_,module,exports){
+},{"./React":29}],66:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -10383,17 +11337,17 @@ var ReactMarkupChecksum = {
     existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
     var markupChecksum = adler32(markup);
     return markupChecksum === existingChecksum;
   }
 };
 
 module.exports = ReactMarkupChecksum;
 
-},{"./adler32":99}],60:[function(_dereq_,module,exports){
+},{"./adler32":107}],67:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -10405,25 +11359,28 @@ module.exports = ReactMarkupChecksum;
  * limitations under the License.
  *
  * @providesModule ReactMount
  */
 
 "use strict";
 
 var DOMProperty = _dereq_("./DOMProperty");
-var ReactEventEmitter = _dereq_("./ReactEventEmitter");
+var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
+var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
+var ReactDescriptor = _dereq_("./ReactDescriptor");
 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
 var ReactPerf = _dereq_("./ReactPerf");
 
 var containsNode = _dereq_("./containsNode");
 var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer");
 var instantiateReactComponent = _dereq_("./instantiateReactComponent");
 var invariant = _dereq_("./invariant");
 var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent");
+var warning = _dereq_("./warning");
 
 var SEPARATOR = ReactInstanceHandles.SEPARATOR;
 
 var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
 var nodeCache = {};
 
 var ELEMENT_NODE_TYPE = 1;
 var DOC_NODE_TYPE = 9;
@@ -10596,25 +11553,16 @@ function findDeepestCachedAncestor(targe
  *     <div data-reactid=".3">              <-- Rendered reactRoot of React
  *       // ...                                 component.
  *     </div>
  *   </div>
  *
  * Inside of `container`, the first element rendered is the "reactRoot".
  */
 var ReactMount = {
-  /** Time spent generating markup. */
-  totalInstantiationTime: 0,
-
-  /** Time spent inserting markup into the DOM. */
-  totalInjectionTime: 0,
-
-  /** Whether support for touch events should be initialized. */
-  useTouchEvents: false,
-
   /** Exposed for debugging purposes **/
   _instancesByReactRootID: instancesByReactRootID,
 
   /**
    * This is a hook provided to support rendering React components while
    * ensuring that the apparent scroll position of its `container` does not
    * change.
    *
@@ -10665,17 +11613,17 @@ var ReactMount = {
         container.nodeType === DOC_NODE_TYPE
       ),
       '_registerComponent(...): Target container is not a DOM element.'
     ) : invariant(container && (
       container.nodeType === ELEMENT_NODE_TYPE ||
       container.nodeType === DOC_NODE_TYPE
     )));
 
-    ReactEventEmitter.ensureScrollValueMonitoring();
+    ReactBrowserEventEmitter.ensureScrollValueMonitoring();
 
     var reactRootID = ReactMount.registerContainer(container);
     instancesByReactRootID[reactRootID] = nextComponent;
     return reactRootID;
   },
 
   /**
    * Render a new component into the DOM.
@@ -10686,16 +11634,26 @@ var ReactMount = {
    */
   _renderNewRootComponent: ReactPerf.measure(
     'ReactMount',
     '_renderNewRootComponent',
     function(
         nextComponent,
         container,
         shouldReuseMarkup) {
+      // Various parts of our code (such as ReactCompositeComponent's
+      // _renderValidatedComponent) assume that calls to render aren't nested;
+      // verify that that's the case.
+      ("production" !== "development" ? warning(
+        ReactCurrentOwner.current == null,
+        '_renderNewRootComponent(): Render methods should be a pure function ' +
+        'of props and state; triggering nested component updates from ' +
+        'render is not allowed. If necessary, trigger nested updates in ' +
+        'componentDidUpdate.'
+      ) : null);
 
       var componentInstance = instantiateReactComponent(nextComponent);
       var reactRootID = ReactMount._registerComponent(
         componentInstance,
         container
       );
       componentInstance.mountComponentIntoNode(
         reactRootID,
@@ -10715,45 +11673,61 @@ var ReactMount = {
 
   /**
    * Renders a React component into the DOM in the supplied `container`.
    *
    * If the React component was previously rendered into `container`, this will
    * perform an update on it and only mutate the DOM as necessary to reflect the
    * latest React component.
    *
-   * @param {ReactComponent} nextComponent Component instance to render.
+   * @param {ReactDescriptor} nextDescriptor Component descriptor to render.
    * @param {DOMElement} container DOM element to render into.
    * @param {?function} callback function triggered on completion
    * @return {ReactComponent} Component instance rendered in `container`.
    */
-  renderComponent: function(nextComponent, container, callback) {
+  renderComponent: function(nextDescriptor, container, callback) {
+    ("production" !== "development" ? invariant(
+      ReactDescriptor.isValidDescriptor(nextDescriptor),
+      'renderComponent(): Invalid component descriptor.%s',
+      (
+        ReactDescriptor.isValidFactory(nextDescriptor) ?
+          ' Instead of passing a component class, make sure to instantiate ' +
+          'it first by calling it with props.' :
+        // Check if it quacks like a descriptor
+        typeof nextDescriptor.props !== "undefined" ?
+          ' This may be caused by unintentionally loading two independent ' +
+          'copies of React.' :
+          ''
+      )
+    ) : invariant(ReactDescriptor.isValidDescriptor(nextDescriptor)));
+
     var prevComponent = instancesByReactRootID[getReactRootID(container)];
 
     if (prevComponent) {
-      if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
+      var prevDescriptor = prevComponent._descriptor;
+      if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
         return ReactMount._updateRootComponent(
           prevComponent,
-          nextComponent,
+          nextDescriptor,
           container,
           callback
         );
       } else {
         ReactMount.unmountComponentAtNode(container);
       }
     }
 
     var reactRootElement = getReactRootElementInContainer(container);
     var containerHasReactMarkup =
       reactRootElement && ReactMount.isRenderedByReact(reactRootElement);
 
     var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
 
     var component = ReactMount._renderNewRootComponent(
-      nextComponent,
+      nextDescriptor,
       container,
       shouldReuseMarkup
     );
     callback && callback.call(component);
     return component;
   },
 
   /**
@@ -10813,16 +11787,28 @@ var ReactMount = {
   /**
    * Unmounts and destroys the React component rendered in the `container`.
    *
    * @param {DOMElement} container DOM element containing a React component.
    * @return {boolean} True if a component was found in and unmounted from
    *                   `container`
    */
   unmountComponentAtNode: function(container) {
+    // Various parts of our code (such as ReactCompositeComponent's
+    // _renderValidatedComponent) assume that calls to render aren't nested;
+    // verify that that's the case. (Strictly speaking, unmounting won't cause a
+    // render but we still don't expect to be in a render call here.)
+    ("production" !== "development" ? warning(
+      ReactCurrentOwner.current == null,
+      'unmountComponentAtNode(): Render methods should be a pure function of ' +
+      'props and state; triggering nested component updates from render is ' +
+      'not allowed. If necessary, trigger nested updates in ' +
+      'componentDidUpdate.'
+    ) : null);
+
     var reactRootID = getReactRootID(container);
     var component = instancesByReactRootID[reactRootID];
     if (!component) {
       return false;
     }
     ReactMount.unmountComponentFromNode(component, container);
     delete instancesByReactRootID[reactRootID];
     delete containersByReactRootID[reactRootID];
@@ -11008,19 +11994,19 @@ var ReactMount = {
     }
 
     firstChildren.length = 0;
 
     ("production" !== "development" ? invariant(
       false,
       'findComponentRoot(..., %s): Unable to find element. This probably ' +
       'means the DOM was unexpectedly mutated (e.g., by the browser), ' +
-      'usually due to forgetting a <tbody> when using tables or nesting <p> ' +
-      'or <a> tags. Try inspecting the child nodes of the element with React ' +
-      'ID `%s`.',
+      'usually due to forgetting a <tbody> when using tables, nesting <p> ' +
+      'or <a> tags, or using non-SVG elements in an <svg> parent. Try ' +
+      'inspecting the child nodes of the element with React ID `%s`.',
       targetID,
       ReactMount.getID(ancestorNode)
     ) : invariant(false));
   },
 
 
   /**
    * React ID utilities.
@@ -11034,114 +12020,17 @@ var ReactMount = {
 
   getNode: getNode,
 
   purgeID: purgeID
 };
 
 module.exports = ReactMount;
 
-},{"./DOMProperty":9,"./ReactEventEmitter":52,"./ReactInstanceHandles":57,"./ReactPerf":65,"./containsNode":101,"./getReactRootElementInContainer":120,"./instantiateReactComponent":124,"./invariant":125,"./shouldUpdateReactComponent":144}],61:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2014 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @providesModule ReactMountReady
- */
-
-"use strict";
-
-var PooledClass = _dereq_("./PooledClass");
-
-var mixInto = _dereq_("./mixInto");
-
-/**
- * A specialized pseudo-event module to help keep track of components waiting to
- * be notified when their DOM representations are available for use.
- *
- * This implements `PooledClass`, so you should never need to instantiate this.
- * Instead, use `ReactMountReady.getPooled()`.
- *
- * @param {?array<function>} initialCollection
- * @class ReactMountReady
- * @implements PooledClass
- * @internal
- */
-function ReactMountReady(initialCollection) {
-  this._queue = initialCollection || null;
-}
-
-mixInto(ReactMountReady, {
-
-  /**
-   * Enqueues a callback to be invoked when `notifyAll` is invoked. This is used
-   * to enqueue calls to `componentDidMount` and `componentDidUpdate`.
-   *
-   * @param {ReactComponent} component Component being rendered.
-   * @param {function(DOMElement)} callback Invoked when `notifyAll` is invoked.
-   * @internal
-   */
-  enqueue: function(component, callback) {
-    this._queue = this._queue || [];
-    this._queue.push({component: component, callback: callback});
-  },
-
-  /**
-   * Invokes all enqueued callbacks and clears the queue. This is invoked after
-   * the DOM representation of a component has been created or updated.
-   *
-   * @internal
-   */
-  notifyAll: function() {
-    var queue = this._queue;
-    if (queue) {
-      this._queue = null;
-      for (var i = 0, l = queue.length; i < l; i++) {
-        var component = queue[i].component;
-        var callback = queue[i].callback;
-        callback.call(component);
-      }
-      queue.length = 0;
-    }
-  },
-
-  /**
-   * Resets the internal queue.
-   *
-   * @internal
-   */
-  reset: function() {
-    this._queue = null;
-  },
-
-  /**
-   * `PooledClass` looks for this.
-   */
-  destructor: function() {
-    this.reset();
-  }
-
-});
-
-PooledClass.addPoolingTo(ReactMountReady);
-
-module.exports = ReactMountReady;
-
-},{"./PooledClass":25,"./mixInto":137}],62:[function(_dereq_,module,exports){
+},{"./DOMProperty":11,"./ReactBrowserEventEmitter":31,"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactInstanceHandles":64,"./ReactPerf":71,"./containsNode":109,"./getReactRootElementInContainer":128,"./instantiateReactComponent":133,"./invariant":134,"./shouldUpdateReactComponent":154,"./warning":158}],68:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -11420,30 +12309,31 @@ var ReactMultiChild = {
       // `lastIndex` will be the last index visited in `prevChildren`.
       var lastIndex = 0;
       var nextIndex = 0;
       for (name in nextChildren) {
         if (!nextChildren.hasOwnProperty(name)) {
           continue;
         }
         var prevChild = prevChildren && prevChildren[name];
-        var nextChild = nextChildren[name];
-        if (shouldUpdateReactComponent(prevChild, nextChild)) {
+        var prevDescriptor = prevChild && prevChild._descriptor;
+        var nextDescriptor = nextChildren[name];
+        if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
           this.moveChild(prevChild, nextIndex, lastIndex);
           lastIndex = Math.max(prevChild._mountIndex, lastIndex);
-          prevChild.receiveComponent(nextChild, transaction);
+          prevChild.receiveComponent(nextDescriptor, transaction);
           prevChild._mountIndex = nextIndex;
         } else {
           if (prevChild) {
             // Update `lastIndex` before `_mountIndex` gets unset by unmounting.
             lastIndex = Math.max(prevChild._mountIndex, lastIndex);
             this._unmountChildByName(prevChild, name);
           }
           // The child must be instantiated before it's mounted.
-          var nextChildInstance = instantiateReactComponent(nextChild);
+          var nextChildInstance = instantiateReactComponent(nextDescriptor);
           this._mountChildByNameAtIndex(
             nextChildInstance, name, nextIndex, transaction
           );
         }
         nextIndex++;
       }
       // Remove children that are no longer present.
       for (name in prevChildren) {
@@ -11550,32 +12440,29 @@ var ReactMultiChild = {
      *
      * NOTE: This is part of `updateChildren` and is here for readability.
      *
      * @param {ReactComponent} child Component to unmount.
      * @param {string} name Name of the child in `this._renderedChildren`.
      * @private
      */
     _unmountChildByName: function(child, name) {
-      // TODO: When is this not true?
-      if (ReactComponent.isValidComponent(child)) {
-        this.removeChild(child);
-        child._mountIndex = null;
-        child.unmountComponent();
-        delete this._renderedChildren[name];
-      }
+      this.removeChild(child);
+      child._mountIndex = null;
+      child.unmountComponent();
+      delete this._renderedChildren[name];
     }
 
   }
 
 };
 
 module.exports = ReactMultiChild;
 
-},{"./ReactComponent":31,"./ReactMultiChildUpdateTypes":63,"./flattenChildren":112,"./instantiateReactComponent":124,"./shouldUpdateReactComponent":144}],63:[function(_dereq_,module,exports){
+},{"./ReactComponent":35,"./ReactMultiChildUpdateTypes":69,"./flattenChildren":119,"./instantiateReactComponent":133,"./shouldUpdateReactComponent":154}],69:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
@@ -11605,17 +12492,17 @@ var ReactMultiChildUpdateTypes = keyMirr
   INSERT_MARKUP: null,
   MOVE_EXISTING: null,
   REMOVE_NODE: null,
   TEXT_CONTENT: null
 });
 
 module.exports = ReactMultiChildUpdateTypes;
 
-},{"./keyMirror":131}],64:[function(_dereq_,module,exports){
+},{"./keyMirror":140}],70:[function(_dereq_,module,exports){
 /**
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");