diff options
author | Maximilian Hils <git@maximilianhils.com> | 2015-03-22 14:33:42 +0100 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2015-03-22 14:33:42 +0100 |
commit | cf9f91b0b4abe2020c544981d6dc2e2e85f4b4bd (patch) | |
tree | cd0b08150f7c04ef3537bea525dd58eff5c91a28 /libmproxy/web | |
parent | 6fb661dab518c036e9333d360f2efc91bc2631ab (diff) | |
download | mitmproxy-cf9f91b0b4abe2020c544981d6dc2e2e85f4b4bd.tar.gz mitmproxy-cf9f91b0b4abe2020c544981d6dc2e2e85f4b4bd.tar.bz2 mitmproxy-cf9f91b0b4abe2020c544981d6dc2e2e85f4b4bd.zip |
web: upgrade to react 0.13
Diffstat (limited to 'libmproxy/web')
-rw-r--r-- | libmproxy/web/static/app.js | 44 | ||||
-rw-r--r-- | libmproxy/web/static/vendor.css | 46 | ||||
-rw-r--r-- | libmproxy/web/static/vendor.js | 11041 |
3 files changed, 6511 insertions, 4620 deletions
diff --git a/libmproxy/web/static/app.js b/libmproxy/web/static/app.js index 2254b415..4f3998a9 100644 --- a/libmproxy/web/static/app.js +++ b/libmproxy/web/static/app.js @@ -478,31 +478,43 @@ var StickyHeadMixin = { var Navigation = _.extend({}, ReactRouter.Navigation, { setQuery: function (dict) { - var q = this.context.getCurrentQuery(); + var q = this.context.router.getCurrentQuery(); for(var i in dict){ if(dict.hasOwnProperty(i)){ q[i] = dict[i] || undefined; //falsey values shall be removed. } } q._ = "_"; // workaround for https://github.com/rackt/react-router/pull/957 - this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q); + this.replaceWith(this.context.router.getCurrentPath(), this.context.router.getCurrentParams(), q); }, replaceWith: function(routeNameOrPath, params, query) { if(routeNameOrPath === undefined){ - routeNameOrPath = this.context.getCurrentPath(); + routeNameOrPath = this.context.router.getCurrentPath(); } if(params === undefined){ - params = this.context.getCurrentParams(); + params = this.context.router.getCurrentParams(); } if(query === undefined) { - query = this.context.getCurrentQuery(); + query = this.context.router.getCurrentQuery(); } - // FIXME: react-router is just broken. - ReactRouter.Navigation.replaceWith.call(this, routeNameOrPath, params, query); + // FIXME: react-router is just broken, + // we hopefully just need to wait for the next release with https://github.com/rackt/react-router/pull/957. + this.context.router.replaceWith(routeNameOrPath, params, query); + } +}); + +// react-router is fairly good at changing its API regularly. +// We keep the old method for now - if it should turn out that their changes are permanent, +// we may remove this mixin and access react-router directly again. +var State = _.extend({}, ReactRouter.State, { + getQuery: function(){ + return this.context.router.getCurrentQuery(); + }, + getParams: function(){ + return this.context.router.getCurrentParams(); } }); -_.extend(Navigation.contextTypes, ReactRouter.State.contextTypes); var Splitter = React.createClass({displayName: "Splitter", getDefaultProps: function () { @@ -610,7 +622,7 @@ var Splitter = React.createClass({displayName: "Splitter", }); module.exports = { - State: ReactRouter.State, // keep here - react-router is pretty buggy, we may need workarounds in the future. + State: State, Navigation: Navigation, StickyHeadMixin: StickyHeadMixin, AutoScrollMixin: AutoScrollMixin, @@ -2166,15 +2178,17 @@ var Header = React.createClass({displayName: "Header", }, render: function () { var header = header_entries.map(function (entry, i) { - var classes = React.addons.classSet({ - active: entry == this.state.active - }); + var className; + if(entry === this.state.active){ + className = "active"; + } else { + className = ""; + } return ( React.createElement("a", {key: i, href: "#", - className: classes, - onClick: this.handleClick.bind(this, entry) - }, + className: className, + onClick: this.handleClick.bind(this, entry)}, entry.title ) ); diff --git a/libmproxy/web/static/vendor.css b/libmproxy/web/static/vendor.css index 149372c8..a170c49a 100644 --- a/libmproxy/web/static/vendor.css +++ b/libmproxy/web/static/vendor.css @@ -945,12 +945,24 @@ th { .glyphicon-bitcoin:before { content: "\e227"; } +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} .glyphicon-yen:before { content: "\00a5"; } +.glyphicon-jpy:before { + content: "\00a5"; +} .glyphicon-ruble:before { content: "\20bd"; } +.glyphicon-rub:before { + content: "\20bd"; +} .glyphicon-scale:before { content: "\e230"; } @@ -1147,6 +1159,9 @@ hr { overflow: visible; clip: auto; } +[role="button"] { + cursor: pointer; +} h1, h2, h3, @@ -2548,10 +2563,13 @@ output { .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - cursor: not-allowed; background-color: #eeeeee; opacity: 1; } +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} textarea.form-control { height: auto; } @@ -2618,6 +2636,7 @@ input[type="search"] { } .radio-inline, .checkbox-inline { + position: relative; display: inline-block; padding-left: 20px; margin-bottom: 0; @@ -2654,6 +2673,7 @@ fieldset[disabled] .checkbox label { padding-top: 7px; padding-bottom: 7px; margin-bottom: 0; + min-height: 34px; } .form-control-static.input-lg, .form-control-static.input-sm { @@ -2695,6 +2715,7 @@ select[multiple].form-group-sm .form-control { padding: 5px 10px; font-size: 12px; line-height: 1.5; + min-height: 32px; } .input-lg { height: 46px; @@ -2731,6 +2752,7 @@ select[multiple].form-group-lg .form-control { padding: 10px 16px; font-size: 18px; line-height: 1.3333333; + min-height: 38px; } .has-feedback { position: relative; @@ -3348,11 +3370,9 @@ input[type="button"].btn-block { } .collapse { display: none; - visibility: hidden; } .collapse.in { display: block; - visibility: visible; } tr.collapse.in { display: table-row; @@ -3377,7 +3397,7 @@ tbody.collapse.in { height: 0; margin-left: 2px; vertical-align: middle; - border-top: 4px solid; + border-top: 4px dashed; border-right: 4px solid transparent; border-left: 4px solid transparent; } @@ -4016,11 +4036,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn { } .tab-content > .tab-pane { display: none; - visibility: hidden; } .tab-content > .active { display: block; - visibility: visible; } .nav-tabs .dropdown-menu { margin-top: -1px; @@ -4062,7 +4080,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { } .navbar-collapse.collapse { display: block !important; - visibility: visible !important; height: auto !important; padding-bottom: 0; overflow: visible !important; @@ -4791,7 +4808,8 @@ a.label:focus { position: relative; top: -1px; } -.btn-xs .badge { +.btn-xs .badge, +.btn-group-xs > .btn .badge { top: 0; padding: 1px 5px; } @@ -5614,10 +5632,10 @@ a.list-group-item-danger.active:focus { width: 100%; border: 0; } -.embed-responsive.embed-responsive-16by9 { +.embed-responsive-16by9 { padding-bottom: 56.25%; } -.embed-responsive.embed-responsive-4by3 { +.embed-responsive-4by3 { padding-bottom: 75%; } .well { @@ -5678,7 +5696,7 @@ button.close { right: 0; bottom: 0; left: 0; - z-index: 1040; + z-index: 1050; -webkit-overflow-scrolling: touch; outline: 0; } @@ -5719,10 +5737,12 @@ button.close { outline: 0; } .modal-backdrop { - position: absolute; + position: fixed; top: 0; right: 0; + bottom: 0; left: 0; + z-index: 1040; background-color: #000000; } .modal-backdrop.fade { @@ -5793,7 +5813,6 @@ button.close { position: absolute; z-index: 1070; display: block; - visibility: visible; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; @@ -6316,7 +6335,6 @@ button.close { } .hidden { display: none !important; - visibility: hidden !important; } .affix { position: fixed; diff --git a/libmproxy/web/static/vendor.js b/libmproxy/web/static/vendor.js index d98e50d9..6b34edb9 100644 --- a/libmproxy/web/static/vendor.js +++ b/libmproxy/web/static/vendor.js @@ -394,49 +394,432 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; },{}],4:[function(require,module,exports){ -"use strict"; +module.exports = require('./lib/'); -/** - * Represents a cancellation caused by navigating away - * before the previous transition has fully resolved. - */ -function Cancellation() {} +},{"./lib/":5}],5:[function(require,module,exports){ +// Load modules -module.exports = Cancellation; -},{}],5:[function(require,module,exports){ -"use strict"; +var Stringify = require('./stringify'); +var Parse = require('./parse'); -var warning = require("react/lib/warning"); -var invariant = require("react/lib/invariant"); -function checkPropTypes(componentName, propTypes, props) { - for (var propName in propTypes) { - if (propTypes.hasOwnProperty(propName)) { - var error = propTypes[propName](props, propName, componentName); +// Declare internals - if (error instanceof Error) warning(false, error.message); +var internals = {}; + + +module.exports = { + stringify: Stringify, + parse: Parse +}; + +},{"./parse":6,"./stringify":7}],6:[function(require,module,exports){ +// Load modules + +var Utils = require('./utils'); + + +// Declare internals + +var internals = { + delimiter: '&', + depth: 5, + arrayLimit: 20, + parameterLimit: 1000 +}; + + +internals.parseValues = function (str, options) { + + var obj = {}; + var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); + + for (var i = 0, il = parts.length; i < il; ++i) { + var part = parts[i]; + var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1; + + if (pos === -1) { + obj[Utils.decode(part)] = ''; + } + else { + var key = Utils.decode(part.slice(0, pos)); + var val = Utils.decode(part.slice(pos + 1)); + + if (Object.prototype.hasOwnProperty(key)) { + continue; + } + + if (!obj.hasOwnProperty(key)) { + obj[key] = val; + } + else { + obj[key] = [].concat(obj[key]).concat(val); + } + } } - } -} -var Configuration = { + return obj; +}; - statics: { - validateProps: function validateProps(props) { - checkPropTypes(this.displayName, this.propTypes, props); +internals.parseObject = function (chain, val, options) { + + if (!chain.length) { + return val; } - }, + var root = chain.shift(); - render: function render() { - invariant(false, "%s elements are for router configuration only and should not be rendered", this.constructor.displayName); - } + var obj = {}; + if (root === '[]') { + obj = []; + obj = obj.concat(internals.parseObject(chain, val, options)); + } + else { + var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; + var index = parseInt(cleanRoot, 10); + var indexString = '' + index; + if (!isNaN(index) && + root !== cleanRoot && + indexString === cleanRoot && + index >= 0 && + index <= options.arrayLimit) { + + obj = []; + obj[index] = internals.parseObject(chain, val, options); + } + else { + obj[cleanRoot] = internals.parseObject(chain, val, options); + } + } + + return obj; +}; + + +internals.parseKeys = function (key, val, options) { + + if (!key) { + return; + } + + // The regex chunks + + var parent = /^([^\[\]]*)/; + var child = /(\[[^\[\]]*\])/g; + + // Get the parent + + var segment = parent.exec(key); + + // Don't allow them to overwrite object prototype properties + + if (Object.prototype.hasOwnProperty(segment[1])) { + return; + } + + // Stash the parent if it exists + + var keys = []; + if (segment[1]) { + keys.push(segment[1]); + } + + // Loop through children appending to the array until we hit depth + + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + + ++i; + if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { + keys.push(segment[1]); + } + } + + // If there's a remainder, just add whatever is left + + if (segment) { + keys.push('[' + key.slice(segment.index) + ']'); + } + + return internals.parseObject(keys, val, options); +}; + + +module.exports = function (str, options) { + if (str === '' || + str === null || + typeof str === 'undefined') { + + return {}; + } + + options = options || {}; + options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter; + options.depth = typeof options.depth === 'number' ? options.depth : internals.depth; + options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit; + options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit; + + var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str; + var obj = {}; + + // Iterate over the keys and setup the new object + + var keys = Object.keys(tempObj); + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + var newObj = internals.parseKeys(key, tempObj[key], options); + obj = Utils.merge(obj, newObj); + } + + return Utils.compact(obj); +}; + +},{"./utils":8}],7:[function(require,module,exports){ +// Load modules + +var Utils = require('./utils'); + + +// Declare internals + +var internals = { + delimiter: '&', + arrayPrefixGenerators: { + brackets: function (prefix, key) { + return prefix + '[]'; + }, + indices: function (prefix, key) { + return prefix + '[' + key + ']'; + }, + repeat: function (prefix, key) { + return prefix; + } + } }; -module.exports = Configuration; -},{"react/lib/invariant":182,"react/lib/warning":202}],6:[function(require,module,exports){ + +internals.stringify = function (obj, prefix, generateArrayPrefix) { + + if (Utils.isBuffer(obj)) { + obj = obj.toString(); + } + else if (obj instanceof Date) { + obj = obj.toISOString(); + } + else if (obj === null) { + obj = ''; + } + + if (typeof obj === 'string' || + typeof obj === 'number' || + typeof obj === 'boolean') { + + return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)]; + } + + var values = []; + + if (typeof obj === 'undefined') { + return values; + } + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + if (Array.isArray(obj)) { + values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix)); + } + else { + values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix)); + } + } + + return values; +}; + + +module.exports = function (obj, options) { + + options = options || {}; + var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; + + var keys = []; + + if (typeof obj !== 'object' || + obj === null) { + + return ''; + } + + var arrayFormat; + if (options.arrayFormat in internals.arrayPrefixGenerators) { + arrayFormat = options.arrayFormat; + } + else if ('indices' in options) { + arrayFormat = options.indices ? 'indices' : 'repeat'; + } + else { + arrayFormat = 'indices'; + } + + var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat]; + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix)); + } + + return keys.join(delimiter); +}; + +},{"./utils":8}],8:[function(require,module,exports){ +// Load modules + + +// Declare internals + +var internals = {}; + + +exports.arrayToObject = function (source) { + + var obj = {}; + for (var i = 0, il = source.length; i < il; ++i) { + if (typeof source[i] !== 'undefined') { + + obj[i] = source[i]; + } + } + + return obj; +}; + + +exports.merge = function (target, source) { + + if (!source) { + return target; + } + + if (typeof source !== 'object') { + if (Array.isArray(target)) { + target.push(source); + } + else { + target[source] = true; + } + + return target; + } + + if (typeof target !== 'object') { + target = [target].concat(source); + return target; + } + + if (Array.isArray(target) && + !Array.isArray(source)) { + + target = exports.arrayToObject(target); + } + + var keys = Object.keys(source); + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var value = source[key]; + + if (!target[key]) { + target[key] = value; + } + else { + target[key] = exports.merge(target[key], value); + } + } + + return target; +}; + + +exports.decode = function (str) { + + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (e) { + return str; + } +}; + + +exports.compact = function (obj, refs) { + + if (typeof obj !== 'object' || + obj === null) { + + return obj; + } + + refs = refs || []; + var lookup = refs.indexOf(obj); + if (lookup !== -1) { + return refs[lookup]; + } + + refs.push(obj); + + if (Array.isArray(obj)) { + var compacted = []; + + for (var i = 0, il = obj.length; i < il; ++i) { + if (typeof obj[i] !== 'undefined') { + compacted.push(obj[i]); + } + } + + return compacted; + } + + var keys = Object.keys(obj); + for (i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + obj[key] = exports.compact(obj[key], refs); + } + + return obj; +}; + + +exports.isRegExp = function (obj) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +}; + + +exports.isBuffer = function (obj) { + + if (obj === null || + typeof obj === 'undefined') { + + return false; + } + + return !!(obj.constructor && + obj.constructor.isBuffer && + obj.constructor.isBuffer(obj)); +}; + +},{}],9:[function(require,module,exports){ +"use strict"; + +/** + * Represents a cancellation caused by navigating away + * before the previous transition has fully resolved. + */ +function Cancellation() {} + +module.exports = Cancellation; +},{}],10:[function(require,module,exports){ "use strict"; var invariant = require("react/lib/invariant"); @@ -467,10 +850,10 @@ var History = { }; module.exports = History; -},{"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],7:[function(require,module,exports){ +},{"react/lib/ExecutionEnvironment":60,"react/lib/invariant":189}],11:[function(require,module,exports){ "use strict"; -var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; @@ -520,7 +903,7 @@ var Match = (function () { this.routes = routes; } - _prototypeProperties(Match, { + _createClass(Match, null, { findMatch: { /** @@ -537,9 +920,7 @@ var Match = (function () { for (var i = 0, len = routes.length; match == null && i < len; ++i) match = deepSearch(routes[i], pathname, query); return match; - }, - writable: true, - configurable: true + } } }); @@ -547,11 +928,20 @@ var Match = (function () { })(); module.exports = Match; -},{"./PathUtils":10}],8:[function(require,module,exports){ +},{"./PathUtils":13}],12:[function(require,module,exports){ "use strict"; +var warning = require("react/lib/warning"); var PropTypes = require("./PropTypes"); +function deprecatedMethod(routerMethodName, fn) { + return function () { + warning(false, "Router.Navigation is deprecated. Please use this.context.router." + routerMethodName + "() instead"); + + return fn.apply(this, arguments); + }; +} + /** * A mixin for components that modify the URL. * @@ -559,11 +949,11 @@ var PropTypes = require("./PropTypes"); * * var MyLink = React.createClass({ * mixins: [ Router.Navigation ], - * handleClick: function (event) { + * handleClick(event) { * event.preventDefault(); * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' }); * }, - * render: function () { + * render() { * return ( * <a onClick={this.handleClick}>Click me!</a> * ); @@ -573,87 +963,52 @@ var PropTypes = require("./PropTypes"); var Navigation = { contextTypes: { - makePath: PropTypes.func.isRequired, - makeHref: PropTypes.func.isRequired, - transitionTo: PropTypes.func.isRequired, - replaceWith: PropTypes.func.isRequired, - goBack: PropTypes.func.isRequired + router: PropTypes.router.isRequired }, /** * Returns an absolute URL path created from the given route * name, URL parameters, and query values. */ - makePath: function makePath(to, params, query) { - return this.context.makePath(to, params, query); - }, + makePath: deprecatedMethod("makePath", function (to, params, query) { + return this.context.router.makePath(to, params, query); + }), /** * Returns a string that may safely be used as the href of a * link to the route with the given name. */ - makeHref: function makeHref(to, params, query) { - return this.context.makeHref(to, params, query); - }, + makeHref: deprecatedMethod("makeHref", function (to, params, query) { + return this.context.router.makeHref(to, params, query); + }), /** * Transitions to the URL specified in the arguments by pushing * a new URL onto the history stack. */ - transitionTo: function transitionTo(to, params, query) { - this.context.transitionTo(to, params, query); - }, + transitionTo: deprecatedMethod("transitionTo", function (to, params, query) { + this.context.router.transitionTo(to, params, query); + }), /** * Transitions to the URL specified in the arguments by replacing * the current URL in the history stack. */ - replaceWith: function replaceWith(to, params, query) { - this.context.replaceWith(to, params, query); - }, + replaceWith: deprecatedMethod("replaceWith", function (to, params, query) { + this.context.router.replaceWith(to, params, query); + }), /** * Transitions to the previous URL. */ - goBack: function goBack() { - return this.context.goBack(); - } + goBack: deprecatedMethod("goBack", function () { + return this.context.router.goBack(); + }) }; module.exports = Navigation; -},{"./PropTypes":11}],9:[function(require,module,exports){ -"use strict"; - -var PropTypes = require("./PropTypes"); - -/** - * Provides the router with context for Router.Navigation. - */ -var NavigationContext = { - - childContextTypes: { - makePath: PropTypes.func.isRequired, - makeHref: PropTypes.func.isRequired, - transitionTo: PropTypes.func.isRequired, - replaceWith: PropTypes.func.isRequired, - goBack: PropTypes.func.isRequired - }, - - getChildContext: function getChildContext() { - return { - makePath: this.constructor.makePath.bind(this.constructor), - makeHref: this.constructor.makeHref.bind(this.constructor), - transitionTo: this.constructor.transitionTo.bind(this.constructor), - replaceWith: this.constructor.replaceWith.bind(this.constructor), - goBack: this.constructor.goBack.bind(this.constructor) - }; - } - -}; - -module.exports = NavigationContext; -},{"./PropTypes":11}],10:[function(require,module,exports){ +},{"./PropTypes":14,"react/lib/warning":210}],13:[function(require,module,exports){ "use strict"; var invariant = require("react/lib/invariant"); @@ -797,7 +1152,7 @@ var PathUtils = { if (existingQuery) query = query ? merge(existingQuery, query) : existingQuery; - var queryString = qs.stringify(query, { indices: false }); + var queryString = qs.stringify(query, { arrayFormat: "brackets" }); if (queryString) { return PathUtils.withoutQuery(path) + "?" + queryString; @@ -807,27 +1162,39 @@ var PathUtils = { }; module.exports = PathUtils; -},{"qs":38,"qs/lib/utils":42,"react/lib/invariant":182}],11:[function(require,module,exports){ +},{"qs":4,"qs/lib/utils":8,"react/lib/invariant":189}],14:[function(require,module,exports){ "use strict"; var assign = require("react/lib/Object.assign"); var ReactPropTypes = require("react").PropTypes; +var Route = require("./Route"); -var PropTypes = assign({ +var PropTypes = assign({}, ReactPropTypes, { /** - * Requires that the value of a prop be falsy. + * Indicates that a prop should be falsy. */ falsy: function falsy(props, propName, componentName) { if (props[propName]) { return new Error("<" + componentName + "> may not have a \"" + propName + "\" prop"); } - } + }, + + /** + * Indicates that a prop should be a Route object. + */ + route: ReactPropTypes.instanceOf(Route), + + /** + * Indicates that a prop should be a Router object. + */ + //router: ReactPropTypes.instanceOf(Router) // TODO + router: ReactPropTypes.func -}, ReactPropTypes); +}); module.exports = PropTypes; -},{"react":"react","react/lib/Object.assign":70}],12:[function(require,module,exports){ +},{"./Route":16,"react":"react","react/lib/Object.assign":67}],15:[function(require,module,exports){ "use strict"; /** @@ -840,10 +1207,10 @@ function Redirect(to, params, query) { } module.exports = Redirect; -},{}],13:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ "use strict"; -var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; @@ -869,7 +1236,33 @@ var Route = (function () { this.handler = handler; } - _prototypeProperties(Route, { + _createClass(Route, { + appendChild: { + + /** + * Appends the given route to this route's child routes. + */ + + value: function appendChild(route) { + invariant(route instanceof Route, "route.appendChild must use a valid Route"); + + if (!this.childRoutes) this.childRoutes = []; + + this.childRoutes.push(route); + } + }, + toString: { + value: function toString() { + var string = "<Route"; + + if (this.name) string += " name=\"" + this.name + "\""; + + string += " path=\"" + this.path + "\">"; + + return string; + } + } + }, { createRoute: { /** @@ -928,7 +1321,7 @@ var Route = (function () { if (path && !(options.isDefault || options.isNotFound)) { if (PathUtils.isAbsolute(path)) { if (parentRoute) { - invariant(parentRoute.paramNames.length === 0, "You cannot nest path \"%s\" inside \"%s\"; the parent requires URL parameters", path, parentRoute.path); + invariant(path === parentRoute.path || parentRoute.paramNames.length === 0, "You cannot nest path \"%s\" inside \"%s\"; the parent requires URL parameters", path, parentRoute.path); } } else if (parentRoute) { // Relative paths extend their parent. @@ -968,9 +1361,7 @@ var Route = (function () { } return route; - }, - writable: true, - configurable: true + } }, createDefaultRoute: { @@ -981,9 +1372,7 @@ var Route = (function () { value: function createDefaultRoute(options) { return Route.createRoute(assign({}, options, { isDefault: true })); - }, - writable: true, - configurable: true + } }, createNotFoundRoute: { @@ -994,9 +1383,7 @@ var Route = (function () { value: function createNotFoundRoute(options) { return Route.createRoute(assign({}, options, { isNotFound: true })); - }, - writable: true, - configurable: true + } }, createRedirect: { @@ -1020,39 +1407,7 @@ var Route = (function () { transition.redirect(options.to, options.params || params, options.query || query); } })); - }, - writable: true, - configurable: true - } - }, { - appendChild: { - - /** - * Appends the given route to this route's child routes. - */ - - value: function appendChild(route) { - invariant(route instanceof Route, "route.appendChild must use a valid Route"); - - if (!this.childRoutes) this.childRoutes = []; - - this.childRoutes.push(route); - }, - writable: true, - configurable: true - }, - toString: { - value: function toString() { - var string = "<Route"; - - if (this.name) string += " name=\"" + this.name + "\""; - - string += " path=\"" + this.path + "\">"; - - return string; - }, - writable: true, - configurable: true + } } }); @@ -1060,62 +1415,7 @@ var Route = (function () { })(); module.exports = Route; -},{"./PathUtils":10,"react/lib/Object.assign":70,"react/lib/invariant":182,"react/lib/warning":202}],14:[function(require,module,exports){ -"use strict"; - -var React = require("react"); -var assign = require("react/lib/Object.assign"); -var PropTypes = require("./PropTypes"); - -var REF_NAME = "__routeHandler__"; - -var RouteHandlerMixin = { - - contextTypes: { - getRouteAtDepth: PropTypes.func.isRequired, - setRouteComponentAtDepth: PropTypes.func.isRequired, - routeHandlers: PropTypes.array.isRequired - }, - - childContextTypes: { - routeHandlers: PropTypes.array.isRequired - }, - - getChildContext: function getChildContext() { - return { - routeHandlers: this.context.routeHandlers.concat([this]) - }; - }, - - componentDidMount: function componentDidMount() { - this._updateRouteComponent(this.refs[REF_NAME]); - }, - - componentDidUpdate: function componentDidUpdate() { - this._updateRouteComponent(this.refs[REF_NAME]); - }, - - componentWillUnmount: function componentWillUnmount() { - this._updateRouteComponent(null); - }, - - _updateRouteComponent: function _updateRouteComponent(component) { - this.context.setRouteComponentAtDepth(this.getRouteDepth(), component); - }, - - getRouteDepth: function getRouteDepth() { - return this.context.routeHandlers.length; - }, - - createChildRouteHandler: function createChildRouteHandler(props) { - var route = this.context.getRouteAtDepth(this.getRouteDepth()); - return route ? React.createElement(route.handler, assign({}, props || this.props, { ref: REF_NAME })) : null; - } - -}; - -module.exports = RouteHandlerMixin; -},{"./PropTypes":11,"react":"react","react/lib/Object.assign":70}],15:[function(require,module,exports){ +},{"./PathUtils":13,"react/lib/Object.assign":67,"react/lib/invariant":189,"react/lib/warning":210}],17:[function(require,module,exports){ "use strict"; var invariant = require("react/lib/invariant"); @@ -1191,11 +1491,20 @@ var ScrollHistory = { }; module.exports = ScrollHistory; -},{"./getWindowScrollPosition":30,"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],16:[function(require,module,exports){ +},{"./getWindowScrollPosition":32,"react/lib/ExecutionEnvironment":60,"react/lib/invariant":189}],18:[function(require,module,exports){ "use strict"; +var warning = require("react/lib/warning"); var PropTypes = require("./PropTypes"); +function deprecatedMethod(routerMethodName, fn) { + return function () { + warning(false, "Router.State is deprecated. Please use this.context.router." + routerMethodName + "() instead"); + + return fn.apply(this, arguments); + }; +} + /** * A mixin for components that need to know the path, routes, URL * params and query that are currently active. @@ -1204,7 +1513,7 @@ var PropTypes = require("./PropTypes"); * * var AboutLink = React.createClass({ * mixins: [ Router.State ], - * render: function () { + * render() { * var className = this.props.className; * * if (this.isActive('about')) @@ -1217,158 +1526,56 @@ var PropTypes = require("./PropTypes"); var State = { contextTypes: { - getCurrentPath: PropTypes.func.isRequired, - getCurrentRoutes: PropTypes.func.isRequired, - getCurrentPathname: PropTypes.func.isRequired, - getCurrentParams: PropTypes.func.isRequired, - getCurrentQuery: PropTypes.func.isRequired, - isActive: PropTypes.func.isRequired + router: PropTypes.router.isRequired }, /** * Returns the current URL path. */ - getPath: function getPath() { - return this.context.getCurrentPath(); - }, - - /** - * Returns an array of the routes that are currently active. - */ - getRoutes: function getRoutes() { - return this.context.getCurrentRoutes(); - }, + getPath: deprecatedMethod("getCurrentPath", function () { + return this.context.router.getCurrentPath(); + }), /** * Returns the current URL path without the query string. */ - getPathname: function getPathname() { - return this.context.getCurrentPathname(); - }, + getPathname: deprecatedMethod("getCurrentPathname", function () { + return this.context.router.getCurrentPathname(); + }), /** * Returns an object of the URL params that are currently active. */ - getParams: function getParams() { - return this.context.getCurrentParams(); - }, + getParams: deprecatedMethod("getCurrentParams", function () { + return this.context.router.getCurrentParams(); + }), /** * Returns an object of the query params that are currently active. */ - getQuery: function getQuery() { - return this.context.getCurrentQuery(); - }, - - /** - * A helper method to determine if a given route, params, and query - * are active. - */ - isActive: function isActive(to, params, query) { - return this.context.isActive(to, params, query); - } - -}; - -module.exports = State; -},{"./PropTypes":11}],17:[function(require,module,exports){ -"use strict"; - -var assign = require("react/lib/Object.assign"); -var PropTypes = require("./PropTypes"); -var PathUtils = require("./PathUtils"); - -function routeIsActive(activeRoutes, routeName) { - return activeRoutes.some(function (route) { - return route.name === routeName; - }); -} - -function paramsAreActive(activeParams, params) { - for (var property in params) if (String(activeParams[property]) !== String(params[property])) { - return false; - }return true; -} - -function queryIsActive(activeQuery, query) { - for (var property in query) if (String(activeQuery[property]) !== String(query[property])) { - return false; - }return true; -} - -/** - * Provides the router with context for Router.State. - */ -var StateContext = { - - /** - * Returns the current URL path + query string. - */ - getCurrentPath: function getCurrentPath() { - return this.state.path; - }, - - /** - * Returns a read-only array of the currently active routes. - */ - getCurrentRoutes: function getCurrentRoutes() { - return this.state.routes.slice(0); - }, - - /** - * Returns the current URL path without the query string. - */ - getCurrentPathname: function getCurrentPathname() { - return this.state.pathname; - }, - - /** - * Returns a read-only object of the currently active URL parameters. - */ - getCurrentParams: function getCurrentParams() { - return assign({}, this.state.params); - }, + getQuery: deprecatedMethod("getCurrentQuery", function () { + return this.context.router.getCurrentQuery(); + }), /** - * Returns a read-only object of the currently active query parameters. + * Returns an array of the routes that are currently active. */ - getCurrentQuery: function getCurrentQuery() { - return assign({}, this.state.query); - }, + getRoutes: deprecatedMethod("getCurrentRoutes", function () { + return this.context.router.getCurrentRoutes(); + }), /** - * Returns true if the given route, params, and query are active. + * A helper method to determine if a given route, params, and query + * are active. */ - isActive: function isActive(to, params, query) { - if (PathUtils.isAbsolute(to)) { - return to === this.state.path; - }return routeIsActive(this.state.routes, to) && paramsAreActive(this.state.params, params) && (query == null || queryIsActive(this.state.query, query)); - }, - - childContextTypes: { - getCurrentPath: PropTypes.func.isRequired, - getCurrentRoutes: PropTypes.func.isRequired, - getCurrentPathname: PropTypes.func.isRequired, - getCurrentParams: PropTypes.func.isRequired, - getCurrentQuery: PropTypes.func.isRequired, - isActive: PropTypes.func.isRequired - }, - - getChildContext: function getChildContext() { - return { - getCurrentPath: this.getCurrentPath, - getCurrentRoutes: this.getCurrentRoutes, - getCurrentPathname: this.getCurrentPathname, - getCurrentParams: this.getCurrentParams, - getCurrentQuery: this.getCurrentQuery, - isActive: this.isActive - }; - } + isActive: deprecatedMethod("isActive", function (to, params, query) { + return this.context.router.isActive(to, params, query); + }) }; -module.exports = StateContext; -},{"./PathUtils":10,"./PropTypes":11,"react/lib/Object.assign":70}],18:[function(require,module,exports){ +module.exports = State; +},{"./PropTypes":14,"react/lib/warning":210}],19:[function(require,module,exports){ "use strict"; /* jshint -W058 */ @@ -1444,7 +1651,7 @@ Transition.to = function (transition, routes, params, query, callback) { }; module.exports = Transition; -},{"./Cancellation":4,"./Redirect":12}],19:[function(require,module,exports){ +},{"./Cancellation":9,"./Redirect":15}],20:[function(require,module,exports){ "use strict"; /** @@ -1470,7 +1677,7 @@ var LocationActions = { }; module.exports = LocationActions; -},{}],20:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ "use strict"; var LocationActions = require("../actions/LocationActions"); @@ -1500,7 +1707,7 @@ var ImitateBrowserBehavior = { }; module.exports = ImitateBrowserBehavior; -},{"../actions/LocationActions":19}],21:[function(require,module,exports){ +},{"../actions/LocationActions":20}],22:[function(require,module,exports){ "use strict"; /** @@ -1516,12 +1723,56 @@ var ScrollToTopBehavior = { }; module.exports = ScrollToTopBehavior; -},{}],22:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ "use strict"; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + +/** + * This component is necessary to get around a context warning + * present in React 0.13.0. It sovles this by providing a separation + * between the "owner" and "parent" contexts. + */ + var React = require("react"); -var Configuration = require("../Configuration"); + +var ContextWrapper = (function (_React$Component) { + function ContextWrapper() { + _classCallCheck(this, ContextWrapper); + + if (_React$Component != null) { + _React$Component.apply(this, arguments); + } + } + + _inherits(ContextWrapper, _React$Component); + + _createClass(ContextWrapper, { + render: { + value: function render() { + return this.props.children; + } + } + }); + + return ContextWrapper; +})(React.Component); + +module.exports = ContextWrapper; +},{"react":"react"}],24:[function(require,module,exports){ +"use strict"; + +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var PropTypes = require("../PropTypes"); +var RouteHandler = require("./RouteHandler"); +var Route = require("./Route"); /** * A <DefaultRoute> component is a special kind of <Route> that @@ -1529,32 +1780,49 @@ var PropTypes = require("../PropTypes"); * Only one such route may be used at any given level in the * route hierarchy. */ -var DefaultRoute = React.createClass({ - - displayName: "DefaultRoute", - mixins: [Configuration], +var DefaultRoute = (function (_Route) { + function DefaultRoute() { + _classCallCheck(this, DefaultRoute); - propTypes: { - name: PropTypes.string, - path: PropTypes.falsy, - children: PropTypes.falsy, - handler: PropTypes.func.isRequired + if (_Route != null) { + _Route.apply(this, arguments); + } } -}); + _inherits(DefaultRoute, _Route); + + return DefaultRoute; +})(Route); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + +DefaultRoute.propTypes = { + name: PropTypes.string, + path: PropTypes.falsy, + children: PropTypes.falsy, + handler: PropTypes.func.isRequired +}; + +DefaultRoute.defaultProps = { + handler: RouteHandler +}; module.exports = DefaultRoute; -},{"../Configuration":5,"../PropTypes":11,"react":"react"}],23:[function(require,module,exports){ +},{"../PropTypes":14,"./Route":28,"./RouteHandler":29}],25:[function(require,module,exports){ "use strict"; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var React = require("react"); -var classSet = require("react/lib/cx"); var assign = require("react/lib/Object.assign"); -var Navigation = require("../Navigation"); -var State = require("../State"); var PropTypes = require("../PropTypes"); -var Route = require("../Route"); function isLeftClickEvent(event) { return event.button === 0; @@ -1582,88 +1850,116 @@ function isModifiedEvent(event) { * * <Link to="showPost" params={{ postID: "123" }} query={{ show:true }}/> */ -var Link = React.createClass({ - displayName: "Link", +var Link = (function (_React$Component) { + function Link() { + _classCallCheck(this, Link); - mixins: [Navigation, State], + if (_React$Component != null) { + _React$Component.apply(this, arguments); + } + } - propTypes: { - activeClassName: PropTypes.string.isRequired, - to: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Route)]), - params: PropTypes.object, - query: PropTypes.object, - activeStyle: PropTypes.object, - onClick: PropTypes.func - }, + _inherits(Link, _React$Component); - getDefaultProps: function getDefaultProps() { - return { - activeClassName: "active" - }; - }, + _createClass(Link, { + handleClick: { + value: function handleClick(event) { + var allowTransition = true; + var clickResult; - handleClick: function handleClick(event) { - var allowTransition = true; - var clickResult; + if (this.props.onClick) clickResult = this.props.onClick(event); - if (this.props.onClick) clickResult = this.props.onClick(event); + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + }if (clickResult === false || event.defaultPrevented === true) allowTransition = false; - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - }if (clickResult === false || event.defaultPrevented === true) allowTransition = false; + event.preventDefault(); - event.preventDefault(); + if (allowTransition) this.context.router.transitionTo(this.props.to, this.props.params, this.props.query); + } + }, + getHref: { - if (allowTransition) this.transitionTo(this.props.to, this.props.params, this.props.query); - }, + /** + * Returns the value of the "href" attribute to use on the DOM element. + */ - /** - * Returns the value of the "href" attribute to use on the DOM element. - */ - getHref: function getHref() { - return this.makeHref(this.props.to, this.props.params, this.props.query); - }, + value: function getHref() { + return this.context.router.makeHref(this.props.to, this.props.params, this.props.query); + } + }, + getClassName: { - /** - * Returns the value of the "class" attribute to use on the DOM element, which contains - * the value of the activeClassName property when this <Link> is active. - */ - getClassName: function getClassName() { - var classNames = {}; + /** + * Returns the value of the "class" attribute to use on the DOM element, which contains + * the value of the activeClassName property when this <Link> is active. + */ - if (this.props.className) classNames[this.props.className] = true; + value: function getClassName() { + var className = this.props.className; - if (this.getActiveState()) classNames[this.props.activeClassName] = true; + if (this.getActiveState()) className += " " + this.props.activeClassName; - return classSet(classNames); - }, + return className; + } + }, + getActiveState: { + value: function getActiveState() { + return this.context.router.isActive(this.props.to, this.props.params, this.props.query); + } + }, + render: { + value: function render() { + var props = assign({}, this.props, { + href: this.getHref(), + className: this.getClassName(), + onClick: this.handleClick.bind(this) + }); - getActiveState: function getActiveState() { - return this.isActive(this.props.to, this.props.params, this.props.query); - }, + if (props.activeStyle && this.getActiveState()) props.style = props.activeStyle; - render: function render() { - var props = assign({}, this.props, { - href: this.getHref(), - className: this.getClassName(), - onClick: this.handleClick - }); + return React.DOM.a(props, this.props.children); + } + } + }); - if (props.activeStyle && this.getActiveState()) props.style = props.activeStyle; + return Link; +})(React.Component); - return React.DOM.a(props, this.props.children); - } +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 -}); +Link.contextTypes = { + router: PropTypes.router.isRequired +}; + +Link.propTypes = { + activeClassName: PropTypes.string.isRequired, + to: PropTypes.oneOfType([PropTypes.string, PropTypes.route]).isRequired, + params: PropTypes.object, + query: PropTypes.object, + activeStyle: PropTypes.object, + onClick: PropTypes.func +}; + +Link.defaultProps = { + activeClassName: "active", + className: "" +}; module.exports = Link; -},{"../Navigation":8,"../PropTypes":11,"../Route":13,"../State":16,"react":"react","react/lib/Object.assign":70,"react/lib/cx":160}],24:[function(require,module,exports){ +},{"../PropTypes":14,"react":"react","react/lib/Object.assign":67}],26:[function(require,module,exports){ "use strict"; -var React = require("react"); -var Configuration = require("../Configuration"); +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var PropTypes = require("../PropTypes"); +var RouteHandler = require("./RouteHandler"); +var Route = require("./Route"); /** * A <NotFoundRoute> is a special kind of <Route> that @@ -1672,56 +1968,95 @@ var PropTypes = require("../PropTypes"); * Only one such route may be used at any given level in the * route hierarchy. */ -var NotFoundRoute = React.createClass({ - displayName: "NotFoundRoute", +var NotFoundRoute = (function (_Route) { + function NotFoundRoute() { + _classCallCheck(this, NotFoundRoute); - mixins: [Configuration], - - propTypes: { - name: PropTypes.string, - path: PropTypes.falsy, - children: PropTypes.falsy, - handler: PropTypes.func.isRequired + if (_Route != null) { + _Route.apply(this, arguments); + } } -}); + _inherits(NotFoundRoute, _Route); + + return NotFoundRoute; +})(Route); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + +NotFoundRoute.propTypes = { + name: PropTypes.string, + path: PropTypes.falsy, + children: PropTypes.falsy, + handler: PropTypes.func.isRequired +}; + +NotFoundRoute.defaultProps = { + handler: RouteHandler +}; module.exports = NotFoundRoute; -},{"../Configuration":5,"../PropTypes":11,"react":"react"}],25:[function(require,module,exports){ +},{"../PropTypes":14,"./Route":28,"./RouteHandler":29}],27:[function(require,module,exports){ "use strict"; -var React = require("react"); -var Configuration = require("../Configuration"); +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var PropTypes = require("../PropTypes"); +var Route = require("./Route"); /** * A <Redirect> component is a special kind of <Route> that always * redirects to another route when it matches. */ -var Redirect = React.createClass({ - displayName: "Redirect", +var Redirect = (function (_Route) { + function Redirect() { + _classCallCheck(this, Redirect); - mixins: [Configuration], - - propTypes: { - path: PropTypes.string, - from: PropTypes.string, // Alias for path. - to: PropTypes.string, - handler: PropTypes.falsy + if (_Route != null) { + _Route.apply(this, arguments); + } } -}); + _inherits(Redirect, _Route); + + return Redirect; +})(Route); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + +Redirect.propTypes = { + path: PropTypes.string, + from: PropTypes.string, // Alias for path. + to: PropTypes.string, + handler: PropTypes.falsy +}; + +// Redirects should not have a default handler +Redirect.defaultProps = {}; module.exports = Redirect; -},{"../Configuration":5,"../PropTypes":11,"react":"react"}],26:[function(require,module,exports){ +},{"../PropTypes":14,"./Route":28}],28:[function(require,module,exports){ "use strict"; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var React = require("react"); -var Configuration = require("../Configuration"); +var invariant = require("react/lib/invariant"); var PropTypes = require("../PropTypes"); var RouteHandler = require("./RouteHandler"); + /** * <Route> components specify components that are rendered to the page when the * URL matches a given pattern. @@ -1762,52 +2097,147 @@ var RouteHandler = require("./RouteHandler"); * * If no handler is provided for the route, it will render a matched child route. */ -var Route = React.createClass({ - displayName: "Route", +var Route = (function (_React$Component) { + function Route() { + _classCallCheck(this, Route); - mixins: [Configuration], + if (_React$Component != null) { + _React$Component.apply(this, arguments); + } + } - propTypes: { - name: PropTypes.string, - path: PropTypes.string, - handler: PropTypes.func, - ignoreScrollBehavior: PropTypes.bool - }, + _inherits(Route, _React$Component); - getDefaultProps: function getDefaultProps() { - return { - handler: RouteHandler - }; - } + _createClass(Route, { + render: { + value: function render() { + invariant(false, "%s elements are for router configuration only and should not be rendered", this.constructor.name); + } + } + }); -}); + return Route; +})(React.Component); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + +Route.propTypes = { + name: PropTypes.string, + path: PropTypes.string, + handler: PropTypes.func, + ignoreScrollBehavior: PropTypes.bool +}; + +Route.defaultProps = { + handler: RouteHandler +}; module.exports = Route; -},{"../Configuration":5,"../PropTypes":11,"./RouteHandler":27,"react":"react"}],27:[function(require,module,exports){ +},{"../PropTypes":14,"./RouteHandler":29,"react":"react","react/lib/invariant":189}],29:[function(require,module,exports){ "use strict"; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var React = require("react"); -var RouteHandlerMixin = require("../RouteHandlerMixin"); +var ContextWrapper = require("./ContextWrapper"); +var assign = require("react/lib/Object.assign"); +var PropTypes = require("../PropTypes"); + +var REF_NAME = "__routeHandler__"; /** * A <RouteHandler> component renders the active child route handler * when routes are nested. */ -var RouteHandler = React.createClass({ - - displayName: "RouteHandler", - mixins: [RouteHandlerMixin], +var RouteHandler = (function (_React$Component) { + function RouteHandler() { + _classCallCheck(this, RouteHandler); - render: function render() { - return this.createChildRouteHandler(); + if (_React$Component != null) { + _React$Component.apply(this, arguments); + } } -}); + _inherits(RouteHandler, _React$Component); + + _createClass(RouteHandler, { + getChildContext: { + value: function getChildContext() { + return { + routeDepth: this.context.routeDepth + 1 + }; + } + }, + componentDidMount: { + value: function componentDidMount() { + this._updateRouteComponent(this.refs[REF_NAME]); + } + }, + componentDidUpdate: { + value: function componentDidUpdate() { + this._updateRouteComponent(this.refs[REF_NAME]); + } + }, + componentWillUnmount: { + value: function componentWillUnmount() { + this._updateRouteComponent(null); + } + }, + _updateRouteComponent: { + value: function _updateRouteComponent(component) { + this.context.router.setRouteComponentAtDepth(this.getRouteDepth(), component); + } + }, + getRouteDepth: { + value: function getRouteDepth() { + return this.context.routeDepth; + } + }, + createChildRouteHandler: { + value: function createChildRouteHandler(props) { + var route = this.context.router.getRouteAtDepth(this.getRouteDepth()); + return route ? React.createElement(route.handler, assign({}, props || this.props, { ref: REF_NAME })) : null; + } + }, + render: { + value: function render() { + var handler = this.createChildRouteHandler(); + // <script/> for things like <CSSTransitionGroup/> that don't like null + return handler ? React.createElement( + ContextWrapper, + null, + handler + ) : React.createElement("script", null); + } + } + }); + + return RouteHandler; +})(React.Component); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + +RouteHandler.contextTypes = { + routeDepth: PropTypes.number.isRequired, + router: PropTypes.router.isRequired +}; + +RouteHandler.childContextTypes = { + routeDepth: PropTypes.number.isRequired +}; module.exports = RouteHandler; -},{"../RouteHandlerMixin":14,"react":"react"}],28:[function(require,module,exports){ +},{"../PropTypes":14,"./ContextWrapper":23,"react":"react","react/lib/Object.assign":67}],30:[function(require,module,exports){ (function (process){ "use strict"; @@ -1822,9 +2252,7 @@ var HashLocation = require("./locations/HashLocation"); var HistoryLocation = require("./locations/HistoryLocation"); var RefreshLocation = require("./locations/RefreshLocation"); var StaticLocation = require("./locations/StaticLocation"); -var NavigationContext = require("./NavigationContext"); var ScrollHistory = require("./ScrollHistory"); -var StateContext = require("./StateContext"); var createRoutesFromReactChildren = require("./createRoutesFromReactChildren"); var isReactChildren = require("./isReactChildren"); var Transition = require("./Transition"); @@ -1887,6 +2315,24 @@ function addRoutesToNamedRoutes(routes, namedRoutes) { } } +function routeIsActive(activeRoutes, routeName) { + return activeRoutes.some(function (route) { + return route.name === routeName; + }); +} + +function paramsAreActive(activeParams, params) { + for (var property in params) if (String(activeParams[property]) !== String(params[property])) { + return false; + }return true; +} + +function queryIsActive(activeQuery, query) { + for (var property in query) if (String(activeQuery[property]) !== String(query[property])) { + return false; + }return true; +} + /** * Creates and returns a new router using the given options. A router * is a ReactComponent class that knows how to react to changes in the @@ -1946,9 +2392,9 @@ function createRouter(options) { }, clearAllRoutes: function clearAllRoutes() { - this.cancelPendingTransition(); - this.namedRoutes = {}; - this.routes = []; + Router.cancelPendingTransition(); + Router.namedRoutes = {}; + Router.routes = []; }, /** @@ -1957,18 +2403,18 @@ function createRouter(options) { addRoutes: function addRoutes(routes) { if (isReactChildren(routes)) routes = createRoutesFromReactChildren(routes); - addRoutesToNamedRoutes(routes, this.namedRoutes); + addRoutesToNamedRoutes(routes, Router.namedRoutes); - this.routes.push.apply(this.routes, routes); + Router.routes.push.apply(Router.routes, routes); }, /** * Replaces routes of this router from the given children object (see ReactChildren). */ replaceRoutes: function replaceRoutes(routes) { - this.clearAllRoutes(); - this.addRoutes(routes); - this.refresh(); + Router.clearAllRoutes(); + Router.addRoutes(routes); + Router.refresh(); }, /** @@ -1977,7 +2423,7 @@ function createRouter(options) { * match can be made. */ match: function match(path) { - return Match.findMatch(this.routes, path); + return Match.findMatch(Router.routes, path); }, /** @@ -1989,7 +2435,7 @@ function createRouter(options) { if (PathUtils.isAbsolute(to)) { path = to; } else { - var route = to instanceof Route ? to : this.namedRoutes[to]; + var route = to instanceof Route ? to : Router.namedRoutes[to]; invariant(route instanceof Route, "Cannot find a route named \"%s\"", to); @@ -2004,7 +2450,7 @@ function createRouter(options) { * to the route with the given name, URL parameters, and query. */ makeHref: function makeHref(to, params, query) { - var path = this.makePath(to, params, query); + var path = Router.makePath(to, params, query); return location === HashLocation ? "#" + path : path; }, @@ -2013,7 +2459,7 @@ function createRouter(options) { * a new URL onto the history stack. */ transitionTo: function transitionTo(to, params, query) { - var path = this.makePath(to, params, query); + var path = Router.makePath(to, params, query); if (pendingTransition) { // Replace so pending location does not stay in history. @@ -2028,7 +2474,7 @@ function createRouter(options) { * the current URL in the history stack. */ replaceWith: function replaceWith(to, params, query) { - location.replace(this.makePath(to, params, query)); + location.replace(Router.makePath(to, params, query)); }, /** @@ -2059,7 +2505,7 @@ function createRouter(options) { if (abortReason instanceof Cancellation) { return; } else if (abortReason instanceof Redirect) { - location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query)); + location.replace(Router.makePath(abortReason.to, abortReason.params, abortReason.query)); } else { location.pop(); } @@ -2071,7 +2517,7 @@ function createRouter(options) { }, handleLocationChange: function handleLocationChange(change) { - this.dispatch(change.path, change.type); + Router.dispatch(change.path, change.type); }, /** @@ -2091,7 +2537,7 @@ function createRouter(options) { * hooks wait, the transition is fully synchronous. */ dispatch: function dispatch(path, action) { - this.cancelPendingTransition(); + Router.cancelPendingTransition(); var prevPath = state.path; var isRefreshing = action == null; @@ -2102,9 +2548,9 @@ function createRouter(options) { // Record the scroll position as early as possible to // get it before browsers try update it automatically. - if (prevPath && action === LocationActions.PUSH) this.recordScrollPosition(prevPath); + if (prevPath && action === LocationActions.PUSH) Router.recordScrollPosition(prevPath); - var match = this.match(path); + var match = Router.match(path); warning(match != null, "No route matches path \"%s\". Make sure you have <Route path=\"%s\"> somewhere in your routes", path, path); @@ -2132,7 +2578,7 @@ function createRouter(options) { toRoutes = nextRoutes; } - var transition = new Transition(path, this.replaceWith.bind(this, path)); + var transition = new Transition(path, Router.replaceWith.bind(Router, path)); pendingTransition = transition; var fromComponents = mountedComponents.slice(prevRoutes.length - fromRoutes.length); @@ -2161,7 +2607,7 @@ function createRouter(options) { * Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation). */ run: function run(callback) { - invariant(!this.isRunning, "Router is already running"); + invariant(!Router.isRunning, "Router is already running"); dispatchHandler = function (error, transition, newState) { if (error) Router.handleError(error); @@ -2173,18 +2619,18 @@ function createRouter(options) { if (transition.abortReason) { Router.handleAbort(transition.abortReason); } else { - callback.call(this, this, nextState = newState); + callback.call(Router, Router, nextState = newState); } }; if (!(location instanceof StaticLocation)) { if (location.addChangeListener) location.addChangeListener(Router.handleLocationChange); - this.isRunning = true; + Router.isRunning = true; } // Bootstrap using the current path. - this.refresh(); + Router.refresh(); }, refresh: function refresh() { @@ -2192,36 +2638,91 @@ function createRouter(options) { }, stop: function stop() { - this.cancelPendingTransition(); + Router.cancelPendingTransition(); if (location.removeChangeListener) location.removeChangeListener(Router.handleLocationChange); - this.isRunning = false; + Router.isRunning = false; + }, + + getLocation: function getLocation() { + return location; }, getScrollBehavior: function getScrollBehavior() { return scrollBehavior; + }, + + getRouteAtDepth: function getRouteAtDepth(routeDepth) { + var routes = state.routes; + return routes && routes[routeDepth]; + }, + + setRouteComponentAtDepth: function setRouteComponentAtDepth(routeDepth, component) { + mountedComponents[routeDepth] = component; + }, + + /** + * Returns the current URL path + query string. + */ + getCurrentPath: function getCurrentPath() { + return state.path; + }, + + /** + * Returns the current URL path without the query string. + */ + getCurrentPathname: function getCurrentPathname() { + return state.pathname; + }, + + /** + * Returns an object of the currently active URL parameters. + */ + getCurrentParams: function getCurrentParams() { + return state.params; + }, + + /** + * Returns an object of the currently active query parameters. + */ + getCurrentQuery: function getCurrentQuery() { + return state.query; + }, + + /** + * Returns an array of the currently active routes. + */ + getCurrentRoutes: function getCurrentRoutes() { + return state.routes; + }, + + /** + * Returns true if the given route, params, and query are active. + */ + isActive: function isActive(to, params, query) { + if (PathUtils.isAbsolute(to)) { + return to === state.path; + }return routeIsActive(state.routes, to) && paramsAreActive(state.params, params) && (query == null || queryIsActive(state.query, query)); } }, - mixins: [NavigationContext, StateContext, ScrollHistory], + mixins: [ScrollHistory], propTypes: { children: PropTypes.falsy }, childContextTypes: { - getRouteAtDepth: React.PropTypes.func.isRequired, - setRouteComponentAtDepth: React.PropTypes.func.isRequired, - routeHandlers: React.PropTypes.array.isRequired + routeDepth: PropTypes.number.isRequired, + router: PropTypes.router.isRequired }, getChildContext: function getChildContext() { return { - getRouteAtDepth: this.getRouteAtDepth, - setRouteComponentAtDepth: this.setRouteComponentAtDepth, - routeHandlers: [this] + routeDepth: 1, + router: Router }; }, @@ -2237,21 +2738,8 @@ function createRouter(options) { Router.stop(); }, - getLocation: function getLocation() { - return location; - }, - - getRouteAtDepth: function getRouteAtDepth(depth) { - var routes = this.state.routes; - return routes && routes[depth]; - }, - - setRouteComponentAtDepth: function setRouteComponentAtDepth(depth, component) { - mountedComponents[depth] = component; - }, - render: function render() { - var route = this.getRouteAtDepth(0); + var route = Router.getRouteAtDepth(0); return route ? React.createElement(route.handler, this.props) : null; } @@ -2266,17 +2754,16 @@ function createRouter(options) { module.exports = createRouter; }).call(this,require('_process')) -},{"./Cancellation":4,"./History":6,"./Match":7,"./NavigationContext":9,"./PathUtils":10,"./PropTypes":11,"./Redirect":12,"./Route":13,"./ScrollHistory":15,"./StateContext":17,"./Transition":18,"./actions/LocationActions":19,"./behaviors/ImitateBrowserBehavior":20,"./createRoutesFromReactChildren":29,"./isReactChildren":31,"./locations/HashLocation":32,"./locations/HistoryLocation":33,"./locations/RefreshLocation":34,"./locations/StaticLocation":35,"./supportsHistory":37,"_process":1,"react":"react","react/lib/ExecutionEnvironment":64,"react/lib/invariant":182,"react/lib/warning":202}],29:[function(require,module,exports){ +},{"./Cancellation":9,"./History":10,"./Match":11,"./PathUtils":13,"./PropTypes":14,"./Redirect":15,"./Route":16,"./ScrollHistory":17,"./Transition":19,"./actions/LocationActions":20,"./behaviors/ImitateBrowserBehavior":21,"./createRoutesFromReactChildren":31,"./isReactChildren":33,"./locations/HashLocation":34,"./locations/HistoryLocation":35,"./locations/RefreshLocation":36,"./locations/StaticLocation":37,"./supportsHistory":39,"_process":1,"react":"react","react/lib/ExecutionEnvironment":60,"react/lib/invariant":189,"react/lib/warning":210}],31:[function(require,module,exports){ "use strict"; /* jshint -W084 */ - var React = require("react"); var assign = require("react/lib/Object.assign"); var warning = require("react/lib/warning"); -var DefaultRouteType = require("./components/DefaultRoute").type; -var NotFoundRouteType = require("./components/NotFoundRoute").type; -var RedirectType = require("./components/Redirect").type; +var DefaultRoute = require("./components/DefaultRoute"); +var NotFoundRoute = require("./components/NotFoundRoute"); +var Redirect = require("./components/Redirect"); var Route = require("./Route"); function checkPropTypes(componentName, propTypes, props) { @@ -2307,15 +2794,15 @@ function createRouteFromReactElement(element) { if (!React.isValidElement(element)) { return; }var type = element.type; - var props = element.props; + var props = assign({}, type.defaultProps, element.props); if (type.propTypes) checkPropTypes(type.displayName, type.propTypes, props); - if (type === DefaultRouteType) { + if (type === DefaultRoute) { return Route.createDefaultRoute(createRouteOptions(props)); - }if (type === NotFoundRouteType) { + }if (type === NotFoundRoute) { return Route.createNotFoundRoute(createRouteOptions(props)); - }if (type === RedirectType) { + }if (type === Redirect) { return Route.createRedirect(createRouteOptions(props)); }return Route.createRoute(createRouteOptions(props), function () { if (props.children) createRoutesFromReactChildren(props.children); @@ -2349,7 +2836,7 @@ function createRoutesFromReactChildren(children) { } module.exports = createRoutesFromReactChildren; -},{"./Route":13,"./components/DefaultRoute":22,"./components/NotFoundRoute":24,"./components/Redirect":25,"react":"react","react/lib/Object.assign":70,"react/lib/warning":202}],30:[function(require,module,exports){ +},{"./Route":16,"./components/DefaultRoute":24,"./components/NotFoundRoute":26,"./components/Redirect":27,"react":"react","react/lib/Object.assign":67,"react/lib/warning":210}],32:[function(require,module,exports){ "use strict"; var invariant = require("react/lib/invariant"); @@ -2368,7 +2855,7 @@ function getWindowScrollPosition() { } module.exports = getWindowScrollPosition; -},{"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],31:[function(require,module,exports){ +},{"react/lib/ExecutionEnvironment":60,"react/lib/invariant":189}],33:[function(require,module,exports){ "use strict"; var React = require("react"); @@ -2382,51 +2869,38 @@ function isReactChildren(object) { } module.exports = isReactChildren; -},{"react":"react"}],32:[function(require,module,exports){ +},{"react":"react"}],34:[function(require,module,exports){ "use strict"; var LocationActions = require("../actions/LocationActions"); var History = require("../History"); -/** - * Returns the current URL path from the `hash` portion of the URL, including - * query string. - */ -function getHashPath() { - return decodeURI( - // We can't use window.location.hash here because it's not - // consistent across browsers - Firefox will pre-decode it! - window.location.href.split("#")[1] || ""); -} - +var _listeners = []; +var _isListening = false; var _actionType; -function ensureSlash() { - var path = getHashPath(); - - if (path.charAt(0) === "/") { - return true; - }HashLocation.replace("/" + path); - - return false; -} - -var _changeListeners = []; - function notifyChange(type) { if (type === LocationActions.PUSH) History.length += 1; var change = { - path: getHashPath(), + path: HashLocation.getCurrentPath(), type: type }; - _changeListeners.forEach(function (listener) { - listener(change); + _listeners.forEach(function (listener) { + listener.call(HashLocation, change); }); } -var _isListening = false; +function ensureSlash() { + var path = HashLocation.getCurrentPath(); + + if (path.charAt(0) === "/") { + return true; + }HashLocation.replace("/" + path); + + return false; +} function onHashChange() { if (ensureSlash()) { @@ -2445,7 +2919,7 @@ function onHashChange() { var HashLocation = { addChangeListener: function addChangeListener(listener) { - _changeListeners.push(listener); + _listeners.push(listener); // Do this BEFORE listening for hashchange. ensureSlash(); @@ -2462,11 +2936,11 @@ var HashLocation = { }, removeChangeListener: function removeChangeListener(listener) { - _changeListeners = _changeListeners.filter(function (l) { + _listeners = _listeners.filter(function (l) { return l !== listener; }); - if (_changeListeners.length === 0) { + if (_listeners.length === 0) { if (window.removeEventListener) { window.removeEventListener("hashchange", onHashChange, false); } else { @@ -2492,7 +2966,12 @@ var HashLocation = { History.back(); }, - getCurrentPath: getHashPath, + getCurrentPath: function getCurrentPath() { + return decodeURI( + // We can't use window.location.hash here because it's not + // consistent across browsers - Firefox will pre-decode it! + window.location.href.split("#")[1] || ""); + }, toString: function toString() { return "<HashLocation>"; @@ -2501,34 +2980,26 @@ var HashLocation = { }; module.exports = HashLocation; -},{"../History":6,"../actions/LocationActions":19}],33:[function(require,module,exports){ +},{"../History":10,"../actions/LocationActions":20}],35:[function(require,module,exports){ "use strict"; var LocationActions = require("../actions/LocationActions"); var History = require("../History"); -/** - * Returns the current URL path from `window.location`, including query string. - */ -function getWindowPath() { - return decodeURI(window.location.pathname + window.location.search); -} - -var _changeListeners = []; +var _listeners = []; +var _isListening = false; function notifyChange(type) { var change = { - path: getWindowPath(), + path: HistoryLocation.getCurrentPath(), type: type }; - _changeListeners.forEach(function (listener) { - listener(change); + _listeners.forEach(function (listener) { + listener.call(HistoryLocation, change); }); } -var _isListening = false; - function onPopState(event) { if (event.state === undefined) { return; @@ -2543,7 +3014,7 @@ function onPopState(event) { var HistoryLocation = { addChangeListener: function addChangeListener(listener) { - _changeListeners.push(listener); + _listeners.push(listener); if (!_isListening) { if (window.addEventListener) { @@ -2557,11 +3028,11 @@ var HistoryLocation = { }, removeChangeListener: function removeChangeListener(listener) { - _changeListeners = _changeListeners.filter(function (l) { + _listeners = _listeners.filter(function (l) { return l !== listener; }); - if (_changeListeners.length === 0) { + if (_listeners.length === 0) { if (window.addEventListener) { window.removeEventListener("popstate", onPopState, false); } else { @@ -2585,7 +3056,9 @@ var HistoryLocation = { pop: History.back, - getCurrentPath: getWindowPath, + getCurrentPath: function getCurrentPath() { + return decodeURI(window.location.pathname + window.location.search); + }, toString: function toString() { return "<HistoryLocation>"; @@ -2594,7 +3067,7 @@ var HistoryLocation = { }; module.exports = HistoryLocation; -},{"../History":6,"../actions/LocationActions":19}],34:[function(require,module,exports){ +},{"../History":10,"../actions/LocationActions":20}],36:[function(require,module,exports){ "use strict"; var HistoryLocation = require("./HistoryLocation"); @@ -2626,10 +3099,10 @@ var RefreshLocation = { }; module.exports = RefreshLocation; -},{"../History":6,"./HistoryLocation":33}],35:[function(require,module,exports){ +},{"../History":10,"./HistoryLocation":35}],37:[function(require,module,exports){ "use strict"; -var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; @@ -2652,20 +3125,16 @@ var StaticLocation = (function () { this.path = path; } - _prototypeProperties(StaticLocation, null, { + _createClass(StaticLocation, { getCurrentPath: { value: function getCurrentPath() { return this.path; - }, - writable: true, - configurable: true + } }, toString: { value: function toString() { return "<StaticLocation path=\"" + this.path + "\">"; - }, - writable: true, - configurable: true + } } }); @@ -2674,12 +3143,14 @@ var StaticLocation = (function () { // TODO: Include these in the above class definition // once we can use ES7 property initializers. +// https://github.com/babel/babel/issues/619 + StaticLocation.prototype.push = throwCannotModify; StaticLocation.prototype.replace = throwCannotModify; StaticLocation.prototype.pop = throwCannotModify; module.exports = StaticLocation; -},{"react/lib/invariant":182}],36:[function(require,module,exports){ +},{"react/lib/invariant":189}],38:[function(require,module,exports){ "use strict"; var createRouter = require("./createRouter"); @@ -2730,7 +3201,7 @@ function runRouter(routes, location, callback) { } module.exports = runRouter; -},{"./createRouter":28}],37:[function(require,module,exports){ +},{"./createRouter":30}],39:[function(require,module,exports){ "use strict"; function supportsHistory() { @@ -2747,401 +3218,9 @@ function supportsHistory() { } module.exports = supportsHistory; -},{}],38:[function(require,module,exports){ -module.exports = require('./lib/'); - -},{"./lib/":39}],39:[function(require,module,exports){ -// Load modules - -var Stringify = require('./stringify'); -var Parse = require('./parse'); - - -// Declare internals - -var internals = {}; - - -module.exports = { - stringify: Stringify, - parse: Parse -}; - -},{"./parse":40,"./stringify":41}],40:[function(require,module,exports){ -// Load modules - -var Utils = require('./utils'); - - -// Declare internals - -var internals = { - delimiter: '&', - depth: 5, - arrayLimit: 20, - parameterLimit: 1000 -}; - - -internals.parseValues = function (str, options) { - - var obj = {}; - var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); - - for (var i = 0, il = parts.length; i < il; ++i) { - var part = parts[i]; - var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1; - - if (pos === -1) { - obj[Utils.decode(part)] = ''; - } - else { - var key = Utils.decode(part.slice(0, pos)); - var val = Utils.decode(part.slice(pos + 1)); - - if (!obj.hasOwnProperty(key)) { - obj[key] = val; - } - else { - obj[key] = [].concat(obj[key]).concat(val); - } - } - } - - return obj; -}; - - -internals.parseObject = function (chain, val, options) { - - if (!chain.length) { - return val; - } - - var root = chain.shift(); - - var obj = {}; - if (root === '[]') { - obj = []; - obj = obj.concat(internals.parseObject(chain, val, options)); - } - else { - var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; - var index = parseInt(cleanRoot, 10); - var indexString = '' + index; - if (!isNaN(index) && - root !== cleanRoot && - indexString === cleanRoot && - index >= 0 && - index <= options.arrayLimit) { - - obj = []; - obj[index] = internals.parseObject(chain, val, options); - } - else { - obj[cleanRoot] = internals.parseObject(chain, val, options); - } - } - - return obj; -}; - - -internals.parseKeys = function (key, val, options) { - - if (!key) { - return; - } - - // The regex chunks - - var parent = /^([^\[\]]*)/; - var child = /(\[[^\[\]]*\])/g; - - // Get the parent - - var segment = parent.exec(key); - - // Don't allow them to overwrite object prototype properties - - if (Object.prototype.hasOwnProperty(segment[1])) { - return; - } - - // Stash the parent if it exists - - var keys = []; - if (segment[1]) { - keys.push(segment[1]); - } - - // Loop through children appending to the array until we hit depth - - var i = 0; - while ((segment = child.exec(key)) !== null && i < options.depth) { - - ++i; - if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { - keys.push(segment[1]); - } - } - - // If there's a remainder, just add whatever is left - - if (segment) { - keys.push('[' + key.slice(segment.index) + ']'); - } - - return internals.parseObject(keys, val, options); -}; - - -module.exports = function (str, options) { - - if (str === '' || - str === null || - typeof str === 'undefined') { - - return {}; - } - - options = options || {}; - options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter; - options.depth = typeof options.depth === 'number' ? options.depth : internals.depth; - options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit; - options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit; - - var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str; - var obj = {}; - - // Iterate over the keys and setup the new object - - var keys = Object.keys(tempObj); - for (var i = 0, il = keys.length; i < il; ++i) { - var key = keys[i]; - var newObj = internals.parseKeys(key, tempObj[key], options); - obj = Utils.merge(obj, newObj); - } - - return Utils.compact(obj); -}; - -},{"./utils":42}],41:[function(require,module,exports){ -// Load modules - -var Utils = require('./utils'); - - -// Declare internals - -var internals = { - delimiter: '&', - indices: true -}; - - -internals.stringify = function (obj, prefix, options) { - - if (Utils.isBuffer(obj)) { - obj = obj.toString(); - } - else if (obj instanceof Date) { - obj = obj.toISOString(); - } - else if (obj === null) { - obj = ''; - } - - if (typeof obj === 'string' || - typeof obj === 'number' || - typeof obj === 'boolean') { - - return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)]; - } - - var values = []; - - if (typeof obj === 'undefined') { - return values; - } - - var objKeys = Object.keys(obj); - for (var i = 0, il = objKeys.length; i < il; ++i) { - var key = objKeys[i]; - if (!options.indices && - Array.isArray(obj)) { - - values = values.concat(internals.stringify(obj[key], prefix, options)); - } - else { - values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', options)); - } - } - - return values; -}; - - -module.exports = function (obj, options) { - - options = options || {}; - var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; - options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices; - - var keys = []; - - if (typeof obj !== 'object' || - obj === null) { - - return ''; - } - - var objKeys = Object.keys(obj); - for (var i = 0, il = objKeys.length; i < il; ++i) { - var key = objKeys[i]; - keys = keys.concat(internals.stringify(obj[key], key, options)); - } - - return keys.join(delimiter); -}; - -},{"./utils":42}],42:[function(require,module,exports){ -// Load modules - - -// Declare internals - -var internals = {}; - - -exports.arrayToObject = function (source) { - - var obj = {}; - for (var i = 0, il = source.length; i < il; ++i) { - if (typeof source[i] !== 'undefined') { - - obj[i] = source[i]; - } - } - - return obj; -}; - - -exports.merge = function (target, source) { - - if (!source) { - return target; - } - - if (typeof source !== 'object') { - if (Array.isArray(target)) { - target.push(source); - } - else { - target[source] = true; - } - - return target; - } - - if (typeof target !== 'object') { - target = [target].concat(source); - return target; - } - - if (Array.isArray(target) && - !Array.isArray(source)) { - - target = exports.arrayToObject(target); - } - - var keys = Object.keys(source); - for (var k = 0, kl = keys.length; k < kl; ++k) { - var key = keys[k]; - var value = source[key]; - - if (!target[key]) { - target[key] = value; - } - else { - target[key] = exports.merge(target[key], value); - } - } - - return target; -}; - - -exports.decode = function (str) { - - try { - return decodeURIComponent(str.replace(/\+/g, ' ')); - } catch (e) { - return str; - } -}; - - -exports.compact = function (obj, refs) { - - if (typeof obj !== 'object' || - obj === null) { - - return obj; - } - - refs = refs || []; - var lookup = refs.indexOf(obj); - if (lookup !== -1) { - return refs[lookup]; - } - - refs.push(obj); - - if (Array.isArray(obj)) { - var compacted = []; - - for (var i = 0, il = obj.length; i < il; ++i) { - if (typeof obj[i] !== 'undefined') { - compacted.push(obj[i]); - } - } - - return compacted; - } - - var keys = Object.keys(obj); - for (i = 0, il = keys.length; i < il; ++i) { - var key = keys[i]; - obj[key] = exports.compact(obj[key], refs); - } - - return obj; -}; - - -exports.isRegExp = function (obj) { - return Object.prototype.toString.call(obj) === '[object RegExp]'; -}; - - -exports.isBuffer = function (obj) { - - if (obj === null || - typeof obj === 'undefined') { - - return false; - } - - return !!(obj.constructor && - obj.constructor.isBuffer && - obj.constructor.isBuffer(obj)); -}; - -},{}],43:[function(require,module,exports){ +},{}],40:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3152,7 +3231,7 @@ exports.isBuffer = function (obj) { * @typechecks static-only */ -"use strict"; +'use strict'; var focusNode = require("./focusNode"); @@ -3166,9 +3245,9 @@ var AutoFocusMixin = { module.exports = AutoFocusMixin; -},{"./focusNode":167}],44:[function(require,module,exports){ +},{"./focusNode":173}],41:[function(require,module,exports){ /** - * Copyright 2013 Facebook, Inc. + * Copyright 2013-2015 Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3179,19 +3258,48 @@ module.exports = AutoFocusMixin; * @typechecks static-only */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPropagators = require("./EventPropagators"); var ExecutionEnvironment = require("./ExecutionEnvironment"); +var FallbackCompositionState = require("./FallbackCompositionState"); +var SyntheticCompositionEvent = require("./SyntheticCompositionEvent"); var SyntheticInputEvent = require("./SyntheticInputEvent"); var keyOf = require("./keyOf"); +var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space +var START_KEYCODE = 229; + +var canUseCompositionEvent = ( + ExecutionEnvironment.canUseDOM && + 'CompositionEvent' in window +); + +var documentMode = null; +if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) { + documentMode = document.documentMode; +} + +// Webkit offers a very useful `textInput` event that can be used to +// directly represent `beforeInput`. The IE `textinput` event is not as +// useful, so we don't use it. var canUseTextInputEvent = ( ExecutionEnvironment.canUseDOM && 'TextEvent' in window && - !('documentMode' in document || isPresto()) + !documentMode && + !isPresto() +); + +// In IE9+, we have access to composition events, but the data supplied +// by the native compositionend event may be incorrect. Japanese ideographic +// spaces, for instance (\u3000) are not recorded correctly. +var useFallbackCompositionData = ( + ExecutionEnvironment.canUseDOM && + ( + (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11) + ) ); /** @@ -3225,12 +3333,51 @@ var eventTypes = { topLevelTypes.topTextInput, topLevelTypes.topPaste ] + }, + compositionEnd: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionEnd: null}), + captured: keyOf({onCompositionEndCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionEnd, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] + }, + compositionStart: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionStart: null}), + captured: keyOf({onCompositionStartCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionStart, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] + }, + compositionUpdate: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionUpdate: null}), + captured: keyOf({onCompositionUpdateCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionUpdate, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] } }; -// Track characters inserted via keypress and composition events. -var fallbackChars = null; - // Track whether we've ever handled a keypress on the space key. var hasSpaceKeypress = false; @@ -3247,6 +3394,297 @@ function isKeypressCommand(nativeEvent) { ); } + +/** + * Translate native top level events into event types. + * + * @param {string} topLevelType + * @return {object} + */ +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case topLevelTypes.topCompositionStart: + return eventTypes.compositionStart; + case topLevelTypes.topCompositionEnd: + return eventTypes.compositionEnd; + case topLevelTypes.topCompositionUpdate: + return eventTypes.compositionUpdate; + } +} + +/** + * Does our fallback best-guess model think this event signifies that + * composition has begun? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionStart(topLevelType, nativeEvent) { + return ( + topLevelType === topLevelTypes.topKeyDown && + nativeEvent.keyCode === START_KEYCODE + ); +} + +/** + * Does our fallback mode think that this event is the end of composition? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionEnd(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topKeyUp: + // Command keys insert or clear IME input. + return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); + case topLevelTypes.topKeyDown: + // Expect IME keyCode on each keydown. If we get any other + // code we must have exited earlier. + return (nativeEvent.keyCode !== START_KEYCODE); + case topLevelTypes.topKeyPress: + case topLevelTypes.topMouseDown: + case topLevelTypes.topBlur: + // Events are not possible without cancelling IME. + return true; + default: + return false; + } +} + +/** + * Google Input Tools provides composition data via a CustomEvent, + * with the `data` property populated in the `detail` object. If this + * is available on the event object, use it. If not, this is a plain + * composition event and we have nothing special to extract. + * + * @param {object} nativeEvent + * @return {?string} + */ +function getDataFromCustomEvent(nativeEvent) { + var detail = nativeEvent.detail; + if (typeof detail === 'object' && 'data' in detail) { + return detail.data; + } + return null; +} + +// Track the current IME composition fallback object, if any. +var currentComposition = null; + +/** + * @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 {?object} A SyntheticCompositionEvent. + */ +function extractCompositionEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent +) { + var eventType; + var fallbackData; + + if (canUseCompositionEvent) { + eventType = getCompositionEventType(topLevelType); + } else if (!currentComposition) { + if (isFallbackCompositionStart(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionStart; + } + } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionEnd; + } + + if (!eventType) { + return null; + } + + if (useFallbackCompositionData) { + // The current composition is stored statically and must not be + // overwritten while composition continues. + if (!currentComposition && eventType === eventTypes.compositionStart) { + currentComposition = FallbackCompositionState.getPooled(topLevelTarget); + } else if (eventType === eventTypes.compositionEnd) { + if (currentComposition) { + fallbackData = currentComposition.getData(); + } + } + } + + var event = SyntheticCompositionEvent.getPooled( + eventType, + topLevelTargetID, + nativeEvent + ); + + if (fallbackData) { + // Inject data generated from fallback path into the synthetic event. + // This matches the property of native CompositionEventInterface. + event.data = fallbackData; + } else { + var customData = getDataFromCustomEvent(nativeEvent); + if (customData !== null) { + event.data = customData; + } + } + + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The string corresponding to this `beforeInput` event. + */ +function getNativeBeforeInputChars(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topCompositionEnd: + return getDataFromCustomEvent(nativeEvent); + 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 null; + } + + hasSpaceKeypress = true; + return SPACEBAR_CHAR; + + case topLevelTypes.topTextInput: + // Record the characters to be added to the DOM. + var chars = nativeEvent.data; + + // If it's a spacebar character, assume that we have already handled + // it at the keypress level and bail immediately. Android Chrome + // doesn't give us keycodes, so we need to blacklist it. + if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { + return null; + } + + return chars; + + default: + // For other native event types, do nothing. + return null; + } +} + +/** + * For browsers that do not provide the `textInput` event, extract the + * appropriate string to use for SyntheticInputEvent. + * + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The fallback string for this `beforeInput` event. + */ +function getFallbackBeforeInputChars(topLevelType, nativeEvent) { + // If we are currently composing (IME) and using a fallback to do so, + // try to extract the composed characters from the fallback object. + if (currentComposition) { + if ( + topLevelType === topLevelTypes.topCompositionEnd || + isFallbackCompositionEnd(topLevelType, nativeEvent) + ) { + var chars = currentComposition.getData(); + FallbackCompositionState.release(currentComposition); + currentComposition = null; + return chars; + } + return null; + } + + 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. + return null; + 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)) { + return String.fromCharCode(nativeEvent.which); + } + return null; + case topLevelTypes.topCompositionEnd: + return useFallbackCompositionData ? null : nativeEvent.data; + default: + return null; + } +} + +/** + * Extract a SyntheticInputEvent for `beforeInput`, based on either native + * `textInput` or fallback behavior. + * + * @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 {?object} A SyntheticInputEvent. + */ +function extractBeforeInputEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent +) { + var chars; + + if (canUseTextInputEvent) { + chars = getNativeBeforeInputChars(topLevelType, nativeEvent); + } else { + chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); + } + + // If no characters are being inserted, no BeforeInput event should + // be fired. + if (!chars) { + return null; + } + + var event = SyntheticInputEvent.getPooled( + eventTypes.beforeInput, + topLevelTargetID, + nativeEvent + ); + + event.data = chars; + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + /** * Create an `onBeforeInput` event to match * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. @@ -3260,6 +3698,10 @@ function isKeypressCommand(nativeEvent) { * 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. + * + * This plugin is also responsible for emitting `composition` events, thus + * allowing us to share composition fallback code for both `beforeInput` and + * `composition` event types. */ var BeforeInputEventPlugin = { @@ -3274,124 +3716,34 @@ var BeforeInputEventPlugin = { * @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; - } - - hasSpaceKeypress = true; - chars = SPACEBAR_CHAR; - 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. Android Chrome - // doesn't give us keycodes, so we need to blacklist it. - if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { - 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; + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ) { + return [ + extractCompositionEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ), + extractBeforeInputEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ) + ]; } }; module.exports = BeforeInputEventPlugin; -},{"./EventConstants":58,"./EventPropagators":63,"./ExecutionEnvironment":64,"./SyntheticInputEvent":143,"./keyOf":189}],45:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPropagators":59,"./ExecutionEnvironment":60,"./FallbackCompositionState":61,"./SyntheticCompositionEvent":145,"./SyntheticInputEvent":149,"./keyOf":196}],42:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3500,9 +3852,9 @@ var CSSCore = { module.exports = CSSCore; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],46:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],43:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3512,14 +3864,15 @@ module.exports = CSSCore; * @providesModule CSSProperty */ -"use strict"; +'use strict'; /** * CSS properties which accept numbers but are not in units of "px". */ var isUnitlessNumber = { + boxFlex: true, + boxFlexGroup: true, columnCount: true, - fillOpacity: true, flex: true, flexGrow: true, flexShrink: true, @@ -3531,7 +3884,11 @@ var isUnitlessNumber = { orphans: true, widows: true, zIndex: true, - zoom: true + zoom: true, + + // SVG-related properties + fillOpacity: true, + strokeOpacity: true }; /** @@ -3616,10 +3973,10 @@ var CSSProperty = { module.exports = CSSProperty; -},{}],47:[function(require,module,exports){ +},{}],44:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3630,7 +3987,7 @@ module.exports = CSSProperty; * @typechecks static-only */ -"use strict"; +'use strict'; var CSSProperty = require("./CSSProperty"); var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -3654,7 +4011,14 @@ if (ExecutionEnvironment.canUseDOM) { } if ("production" !== process.env.NODE_ENV) { + // 'msTransform' is correct, but the other prefixes should be capitalized + var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; + + // style values shouldn't contain a semicolon + var badStyleValueWithSemicolonPattern = /;\s*$/; + var warnedStyleNames = {}; + var warnedStyleValues = {}; var warnHyphenatedStyleName = function(name) { if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { @@ -3664,10 +4028,54 @@ if ("production" !== process.env.NODE_ENV) { warnedStyleNames[name] = true; ("production" !== process.env.NODE_ENV ? warning( false, - 'Unsupported style property ' + name + '. Did you mean ' + - camelizeStyleName(name) + '?' + 'Unsupported style property %s. Did you mean %s?', + name, + camelizeStyleName(name) + ) : null); + }; + + var warnBadVendoredStyleName = function(name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Unsupported vendor-prefixed style property %s. Did you mean %s?', + name, + name.charAt(0).toUpperCase() + name.slice(1) + ) : null); + }; + + var warnStyleValueWithSemicolon = function(name, value) { + if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { + return; + } + + warnedStyleValues[value] = true; + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Style property values shouldn\'t contain a semicolon. ' + + 'Try "%s: %s" instead.', + name, + value.replace(badStyleValueWithSemicolonPattern, '') ) : null); }; + + /** + * @param {string} name + * @param {*} value + */ + var warnValidStyle = function(name, value) { + if (name.indexOf('-') > -1) { + warnHyphenatedStyleName(name); + } else if (badVendoredStyleNamePattern.test(name)) { + warnBadVendoredStyleName(name); + } else if (badStyleValueWithSemicolonPattern.test(value)) { + warnStyleValueWithSemicolon(name, value); + } + }; } /** @@ -3693,12 +4101,10 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + var styleValue = styles[styleName]; if ("production" !== process.env.NODE_ENV) { - if (styleName.indexOf('-') > -1) { - warnHyphenatedStyleName(styleName); - } + warnValidStyle(styleName, styleValue); } - var styleValue = styles[styleName]; if (styleValue != null) { serialized += processStyleName(styleName) + ':'; serialized += dangerousStyleValue(styleName, styleValue) + ';'; @@ -3721,9 +4127,7 @@ var CSSPropertyOperations = { continue; } if ("production" !== process.env.NODE_ENV) { - if (styleName.indexOf('-') > -1) { - warnHyphenatedStyleName(styleName); - } + warnValidStyle(styleName, styles[styleName]); } var styleValue = dangerousStyleValue(styleName, styles[styleName]); if (styleName === 'float') { @@ -3751,10 +4155,10 @@ var CSSPropertyOperations = { module.exports = CSSPropertyOperations; }).call(this,require('_process')) -},{"./CSSProperty":46,"./ExecutionEnvironment":64,"./camelizeStyleName":154,"./dangerousStyleValue":161,"./hyphenateStyleName":180,"./memoizeStringOnly":191,"./warning":202,"_process":1}],48:[function(require,module,exports){ +},{"./CSSProperty":43,"./ExecutionEnvironment":60,"./camelizeStyleName":160,"./dangerousStyleValue":167,"./hyphenateStyleName":187,"./memoizeStringOnly":198,"./warning":210,"_process":1}],45:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3764,7 +4168,7 @@ module.exports = CSSPropertyOperations; * @providesModule CallbackQueue */ -"use strict"; +'use strict'; var PooledClass = require("./PooledClass"); @@ -3815,7 +4219,7 @@ assign(CallbackQueue.prototype, { if (callbacks) { ("production" !== process.env.NODE_ENV ? invariant( callbacks.length === contexts.length, - "Mismatched list of contexts in callback queue" + 'Mismatched list of contexts in callback queue' ) : invariant(callbacks.length === contexts.length)); this._callbacks = null; this._contexts = null; @@ -3851,9 +4255,9 @@ PooledClass.addPoolingTo(CallbackQueue); module.exports = CallbackQueue; }).call(this,require('_process')) -},{"./Object.assign":70,"./PooledClass":71,"./invariant":182,"_process":1}],49:[function(require,module,exports){ +},{"./Object.assign":67,"./PooledClass":68,"./invariant":189,"_process":1}],46:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -3863,7 +4267,7 @@ module.exports = CallbackQueue; * @providesModule ChangeEventPlugin */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPluginHub = require("./EventPluginHub"); @@ -3919,7 +4323,7 @@ var doesChangeEventBubble = false; if (ExecutionEnvironment.canUseDOM) { // See `handleChange` comment below doesChangeEventBubble = isEventSupported('change') && ( - !('documentMode' in document) || document.documentMode > 8 + (!('documentMode' in document) || document.documentMode > 8) ); } @@ -3996,7 +4400,7 @@ if (ExecutionEnvironment.canUseDOM) { // IE9 claims to support the input event but fails to trigger it when // deleting text, so we ignore its input events isInputEventSupported = isEventSupported('input') && ( - !('documentMode' in document) || document.documentMode > 9 + (!('documentMode' in document) || document.documentMode > 9) ); } @@ -4233,9 +4637,9 @@ var ChangeEventPlugin = { module.exports = ChangeEventPlugin; -},{"./EventConstants":58,"./EventPluginHub":60,"./EventPropagators":63,"./ExecutionEnvironment":64,"./ReactUpdates":132,"./SyntheticEvent":141,"./isEventSupported":183,"./isTextInputElement":185,"./keyOf":189}],50:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPluginHub":56,"./EventPropagators":59,"./ExecutionEnvironment":60,"./ReactUpdates":138,"./SyntheticEvent":147,"./isEventSupported":190,"./isTextInputElement":192,"./keyOf":196}],47:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -4246,7 +4650,7 @@ module.exports = ChangeEventPlugin; * @typechecks */ -"use strict"; +'use strict'; var nextReactRootIndex = 0; @@ -4258,269 +4662,10 @@ var ClientReactRootIndex = { module.exports = ClientReactRootIndex; -},{}],51:[function(require,module,exports){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule CompositionEventPlugin - * @typechecks static-only - */ - -"use strict"; - -var EventConstants = require("./EventConstants"); -var EventPropagators = require("./EventPropagators"); -var ExecutionEnvironment = require("./ExecutionEnvironment"); -var ReactInputSelection = require("./ReactInputSelection"); -var SyntheticCompositionEvent = require("./SyntheticCompositionEvent"); - -var getTextContentAccessor = require("./getTextContentAccessor"); -var keyOf = require("./keyOf"); - -var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space -var START_KEYCODE = 229; - -var useCompositionEvent = ( - ExecutionEnvironment.canUseDOM && - 'CompositionEvent' in window -); - -// 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 && - document.documentMode <= 11 - ) -); - -var topLevelTypes = EventConstants.topLevelTypes; -var currentComposition = null; - -// Events and their corresponding property names. -var eventTypes = { - compositionEnd: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionEnd: null}), - captured: keyOf({onCompositionEndCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionEnd, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - }, - compositionStart: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionStart: null}), - captured: keyOf({onCompositionStartCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionStart, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - }, - compositionUpdate: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionUpdate: null}), - captured: keyOf({onCompositionUpdateCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionUpdate, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - } -}; - -/** - * Translate native top level events into event types. - * - * @param {string} topLevelType - * @return {object} - */ -function getCompositionEventType(topLevelType) { - switch (topLevelType) { - case topLevelTypes.topCompositionStart: - return eventTypes.compositionStart; - case topLevelTypes.topCompositionEnd: - return eventTypes.compositionEnd; - case topLevelTypes.topCompositionUpdate: - return eventTypes.compositionUpdate; - } -} - -/** - * Does our fallback best-guess model think this event signifies that - * composition has begun? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} - */ -function isFallbackStart(topLevelType, nativeEvent) { - return ( - topLevelType === topLevelTypes.topKeyDown && - nativeEvent.keyCode === START_KEYCODE - ); -} - -/** - * Does our fallback mode think that this event is the end of composition? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} - */ -function isFallbackEnd(topLevelType, nativeEvent) { - switch (topLevelType) { - case topLevelTypes.topKeyUp: - // Command keys insert or clear IME input. - return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); - case topLevelTypes.topKeyDown: - // Expect IME keyCode on each keydown. If we get any other - // code we must have exited earlier. - return (nativeEvent.keyCode !== START_KEYCODE); - case topLevelTypes.topKeyPress: - case topLevelTypes.topMouseDown: - case topLevelTypes.topBlur: - // Events are not possible without cancelling IME. - return true; - default: - return false; - } -} - -/** - * Helper class stores information about selection and document state - * so we can figure out what changed at a later date. - * - * @param {DOMEventTarget} root - */ -function FallbackCompositionState(root) { - this.root = root; - this.startSelection = ReactInputSelection.getSelection(root); - this.startValue = this.getText(); -} - -/** - * Get current text of input. - * - * @return {string} - */ -FallbackCompositionState.prototype.getText = function() { - return this.root.value || this.root[getTextContentAccessor()]; -}; - -/** - * Text that has changed since the start of composition. - * - * @return {string} - */ -FallbackCompositionState.prototype.getData = function() { - var endValue = this.getText(); - var prefixLength = this.startSelection.start; - var suffixLength = this.startValue.length - this.startSelection.end; - - return endValue.substr( - prefixLength, - endValue.length - suffixLength - prefixLength - ); -}; - -/** - * This plugin creates `onCompositionStart`, `onCompositionUpdate` and - * `onCompositionEnd` events on inputs, textareas and contentEditable - * nodes. - */ -var CompositionEventPlugin = { - - 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 eventType; - var data; - - if (useCompositionEvent) { - eventType = getCompositionEventType(topLevelType); - } else if (!currentComposition) { - if (isFallbackStart(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionStart; - } - } else if (isFallbackEnd(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionEnd; - } - - if (useFallbackData) { - // The current composition is stored statically and must not be - // overwritten while composition continues. - if (!currentComposition && eventType === eventTypes.compositionStart) { - currentComposition = new FallbackCompositionState(topLevelTarget); - } else if (eventType === eventTypes.compositionEnd) { - if (currentComposition) { - data = currentComposition.getData(); - currentComposition = null; - } - } - } - - if (eventType) { - var event = SyntheticCompositionEvent.getPooled( - eventType, - topLevelTargetID, - nativeEvent - ); - if (data) { - // Inject data generated from fallback path into the synthetic event. - // This matches the property of native CompositionEventInterface. - event.data = data; - } - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; - } - } -}; - -module.exports = CompositionEventPlugin; - -},{"./EventConstants":58,"./EventPropagators":63,"./ExecutionEnvironment":64,"./ReactInputSelection":106,"./SyntheticCompositionEvent":139,"./getTextContentAccessor":177,"./keyOf":189}],52:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -4531,23 +4676,15 @@ module.exports = CompositionEventPlugin; * @typechecks static-only */ -"use strict"; +'use strict'; var Danger = require("./Danger"); var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); -var getTextContentAccessor = require("./getTextContentAccessor"); +var setTextContent = require("./setTextContent"); var invariant = require("./invariant"); /** - * The DOM property to use when setting text content. - * - * @type {string} - * @private - */ -var textContentAccessor = getTextContentAccessor(); - -/** * Inserts `childNode` as a child of `parentNode` at the `index`. * * @param {DOMElement} parentNode Parent node in which to insert. @@ -4566,37 +4703,6 @@ function insertChildAt(parentNode, childNode, index) { ); } -var updateTextContent; -if (textContentAccessor === 'textContent') { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ - updateTextContent = function(node, text) { - node.textContent = text; - }; -} else { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ - updateTextContent = function(node, text) { - // In order to preserve newlines correctly, we can't use .innerText to set - // the contents (see #1080), so we empty the element then append a text node - while (node.firstChild) { - node.removeChild(node.firstChild); - } - if (text) { - var doc = node.ownerDocument || document; - node.appendChild(doc.createTextNode(text)); - } - }; -} - /** * Operations for updating with DOM children. */ @@ -4604,7 +4710,7 @@ var DOMChildrenOperations = { dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, - updateTextContent: updateTextContent, + updateTextContent: setTextContent, /** * Updates a component's children by processing a series of updates. The @@ -4621,7 +4727,8 @@ var DOMChildrenOperations = { // List of children that will be moved or removed. var updatedChildren = null; - for (var i = 0; update = updates[i]; i++) { + for (var i = 0; i < updates.length; i++) { + update = updates[i]; if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { var updatedIndex = update.fromIndex; @@ -4633,7 +4740,7 @@ var DOMChildrenOperations = { '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 tags like <form>, <p>, or <a>, or using non-SVG elements '+ + 'nesting tags like <form>, <p>, or <a>, or using non-SVG elements ' + 'in an <svg> parent. Try inspecting the child nodes of the element ' + 'with React ID `%s`.', updatedIndex, @@ -4658,7 +4765,8 @@ var DOMChildrenOperations = { } } - for (var k = 0; update = updates[k]; k++) { + for (var k = 0; k < updates.length; k++) { + update = updates[k]; switch (update.type) { case ReactMultiChildUpdateTypes.INSERT_MARKUP: insertChildAt( @@ -4675,7 +4783,7 @@ var DOMChildrenOperations = { ); break; case ReactMultiChildUpdateTypes.TEXT_CONTENT: - updateTextContent( + setTextContent( update.parentNode, update.textContent ); @@ -4692,10 +4800,10 @@ var DOMChildrenOperations = { module.exports = DOMChildrenOperations; }).call(this,require('_process')) -},{"./Danger":55,"./ReactMultiChildUpdateTypes":113,"./getTextContentAccessor":177,"./invariant":182,"_process":1}],53:[function(require,module,exports){ +},{"./Danger":51,"./ReactMultiChildUpdateTypes":117,"./invariant":189,"./setTextContent":204,"_process":1}],49:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -4708,7 +4816,7 @@ module.exports = DOMChildrenOperations; /*jslint bitwise: true */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -4991,10 +5099,10 @@ var DOMProperty = { module.exports = DOMProperty; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],54:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],50:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5005,12 +5113,11 @@ module.exports = DOMProperty; * @typechecks static-only */ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); -var escapeTextForBrowser = require("./escapeTextForBrowser"); -var memoizeStringOnly = require("./memoizeStringOnly"); +var quoteAttributeValueForBrowser = require("./quoteAttributeValueForBrowser"); var warning = require("./warning"); function shouldIgnoreValue(name, value) { @@ -5021,10 +5128,6 @@ function shouldIgnoreValue(name, value) { (DOMProperty.hasOverloadedBooleanValue[name] && value === false); } -var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { - return escapeTextForBrowser(name) + '="'; -}); - if ("production" !== process.env.NODE_ENV) { var reactProps = { children: true, @@ -5056,7 +5159,9 @@ if ("production" !== process.env.NODE_ENV) { // logging too much when using transferPropsTo. ("production" !== process.env.NODE_ENV ? warning( standardName == null, - 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' + 'Unknown DOM property %s. Did you mean %s?', + name, + standardName ) : null); }; @@ -5074,8 +5179,8 @@ var DOMPropertyOperations = { * @return {string} Markup string. */ createMarkupForID: function(id) { - return processAttributeNameAndPrefix(DOMProperty.ID_ATTRIBUTE_NAME) + - escapeTextForBrowser(id) + '"'; + return DOMProperty.ID_ATTRIBUTE_NAME + '=' + + quoteAttributeValueForBrowser(id); }, /** @@ -5094,16 +5199,14 @@ var DOMPropertyOperations = { var attributeName = DOMProperty.getAttributeName[name]; if (DOMProperty.hasBooleanValue[name] || (DOMProperty.hasOverloadedBooleanValue[name] && value === true)) { - return escapeTextForBrowser(attributeName); + return attributeName; } - return processAttributeNameAndPrefix(attributeName) + - escapeTextForBrowser(value) + '"'; + return attributeName + '=' + quoteAttributeValueForBrowser(value); } else if (DOMProperty.isCustomAttribute(name)) { if (value == null) { return ''; } - return processAttributeNameAndPrefix(name) + - escapeTextForBrowser(value) + '"'; + return name + '=' + quoteAttributeValueForBrowser(value); } else if ("production" !== process.env.NODE_ENV) { warnUnknownProperty(name); } @@ -5188,10 +5291,10 @@ var DOMPropertyOperations = { module.exports = DOMPropertyOperations; }).call(this,require('_process')) -},{"./DOMProperty":53,"./escapeTextForBrowser":165,"./memoizeStringOnly":191,"./warning":202,"_process":1}],55:[function(require,module,exports){ +},{"./DOMProperty":49,"./quoteAttributeValueForBrowser":202,"./warning":210,"_process":1}],51:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5204,7 +5307,7 @@ module.exports = DOMPropertyOperations; /*jslint evil: true, sub: true */ -"use strict"; +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -5274,7 +5377,8 @@ var Danger = { // This for-in loop skips the holes of the sparse array. The order of // iteration should follow the order of assignment, which happens to match // numerical index order, but we don't rely on that. - for (var resultIndex in markupListByNodeName) { + var resultIndex; + for (resultIndex in markupListByNodeName) { if (markupListByNodeName.hasOwnProperty(resultIndex)) { var markup = markupListByNodeName[resultIndex]; @@ -5295,8 +5399,8 @@ var Danger = { emptyFunction // Do nothing special with <script> tags. ); - for (i = 0; i < renderNodes.length; ++i) { - var renderNode = renderNodes[i]; + for (var j = 0; j < renderNodes.length; ++j) { + var renderNode = renderNodes[j]; if (renderNode.hasAttribute && renderNode.hasAttribute(RESULT_INDEX_ATTR)) { @@ -5316,7 +5420,7 @@ var Danger = { } else if ("production" !== process.env.NODE_ENV) { console.error( - "Danger: Discarding unexpected node:", + 'Danger: Discarding unexpected node:', renderNode ); } @@ -5362,7 +5466,7 @@ var Danger = { 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + '<html> node. This is because browser quirks make this unreliable ' + 'and/or slow. If you want to render to the root you must use ' + - 'server rendering. See renderComponentToString().' + 'server rendering. See React.renderToString().' ) : invariant(oldChild.tagName.toLowerCase() !== 'html')); var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; @@ -5374,9 +5478,9 @@ var Danger = { module.exports = Danger; }).call(this,require('_process')) -},{"./ExecutionEnvironment":64,"./createNodesFromMarkup":159,"./emptyFunction":163,"./getMarkupWrap":174,"./invariant":182,"_process":1}],56:[function(require,module,exports){ +},{"./ExecutionEnvironment":60,"./createNodesFromMarkup":165,"./emptyFunction":168,"./getMarkupWrap":181,"./invariant":189,"_process":1}],52:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5386,9 +5490,9 @@ module.exports = Danger; * @providesModule DefaultEventPluginOrder */ -"use strict"; +'use strict'; - var keyOf = require("./keyOf"); +var keyOf = require("./keyOf"); /** * Module that is injectable into `EventPluginHub`, that specifies a @@ -5406,7 +5510,6 @@ var DefaultEventPluginOrder = [ keyOf({EnterLeaveEventPlugin: null}), keyOf({ChangeEventPlugin: null}), keyOf({SelectEventPlugin: null}), - keyOf({CompositionEventPlugin: null}), keyOf({BeforeInputEventPlugin: null}), keyOf({AnalyticsEventPlugin: null}), keyOf({MobileSafariClickEventPlugin: null}) @@ -5414,9 +5517,9 @@ var DefaultEventPluginOrder = [ module.exports = DefaultEventPluginOrder; -},{"./keyOf":189}],57:[function(require,module,exports){ +},{"./keyOf":196}],53:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5427,7 +5530,7 @@ module.exports = DefaultEventPluginOrder; * @typechecks static-only */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPropagators = require("./EventPropagators"); @@ -5554,9 +5657,9 @@ var EnterLeaveEventPlugin = { module.exports = EnterLeaveEventPlugin; -},{"./EventConstants":58,"./EventPropagators":63,"./ReactMount":111,"./SyntheticMouseEvent":145,"./keyOf":189}],58:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPropagators":59,"./ReactMount":115,"./SyntheticMouseEvent":151,"./keyOf":196}],54:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5566,7 +5669,7 @@ module.exports = EnterLeaveEventPlugin; * @providesModule EventConstants */ -"use strict"; +'use strict'; var keyMirror = require("./keyMirror"); @@ -5626,10 +5729,10 @@ var EventConstants = { module.exports = EventConstants; -},{"./keyMirror":188}],59:[function(require,module,exports){ +},{"./keyMirror":195}],55:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -5716,10 +5819,10 @@ var EventListener = { module.exports = EventListener; }).call(this,require('_process')) -},{"./emptyFunction":163,"_process":1}],60:[function(require,module,exports){ +},{"./emptyFunction":168,"_process":1}],56:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -5729,7 +5832,7 @@ module.exports = EventListener; * @providesModule EventPluginHub */ -"use strict"; +'use strict'; var EventPluginRegistry = require("./EventPluginRegistry"); var EventPluginUtils = require("./EventPluginUtils"); @@ -5778,12 +5881,14 @@ var executeDispatchesAndRelease = function(event) { var InstanceHandle = null; function validateInstanceHandle() { - var invalid = !InstanceHandle|| - !InstanceHandle.traverseTwoPhase || - !InstanceHandle.traverseEnterLeave; - if (invalid) { - throw new Error('InstanceHandle not injected before use!'); - } + var valid = + InstanceHandle && + InstanceHandle.traverseTwoPhase && + InstanceHandle.traverseEnterLeave; + ("production" !== process.env.NODE_ENV ? invariant( + valid, + 'InstanceHandle not injected before use!' + ) : invariant(valid)); } /** @@ -5992,10 +6097,10 @@ var EventPluginHub = { module.exports = EventPluginHub; }).call(this,require('_process')) -},{"./EventPluginRegistry":61,"./EventPluginUtils":62,"./accumulateInto":151,"./forEachAccumulated":168,"./invariant":182,"_process":1}],61:[function(require,module,exports){ +},{"./EventPluginRegistry":57,"./EventPluginUtils":58,"./accumulateInto":157,"./forEachAccumulated":174,"./invariant":189,"_process":1}],57:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6006,7 +6111,7 @@ module.exports = EventPluginHub; * @typechecks static-only */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -6272,10 +6377,10 @@ var EventPluginRegistry = { module.exports = EventPluginRegistry; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],62:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],58:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6285,7 +6390,7 @@ module.exports = EventPluginRegistry; * @providesModule EventPluginUtils */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); @@ -6391,8 +6496,8 @@ function executeDispatch(event, listener, domID) { /** * Standard/simple iteration through an event's collected dispatches. */ -function executeDispatchesInOrder(event, executeDispatch) { - forEachEventDispatch(event, executeDispatch); +function executeDispatchesInOrder(event, cb) { + forEachEventDispatch(event, cb); event._dispatchListeners = null; event._dispatchIDs = null; } @@ -6493,10 +6598,10 @@ var EventPluginUtils = { module.exports = EventPluginUtils; }).call(this,require('_process')) -},{"./EventConstants":58,"./invariant":182,"_process":1}],63:[function(require,module,exports){ +},{"./EventConstants":54,"./invariant":189,"_process":1}],59:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6506,7 +6611,7 @@ module.exports = EventPluginUtils; * @providesModule EventPropagators */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPluginHub = require("./EventPluginHub"); @@ -6635,9 +6740,9 @@ var EventPropagators = { module.exports = EventPropagators; }).call(this,require('_process')) -},{"./EventConstants":58,"./EventPluginHub":60,"./accumulateInto":151,"./forEachAccumulated":168,"_process":1}],64:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPluginHub":56,"./accumulateInto":157,"./forEachAccumulated":174,"_process":1}],60:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6652,9 +6757,8 @@ module.exports = EventPropagators; "use strict"; var canUseDOM = !!( - typeof window !== 'undefined' && - window.document && - window.document.createElement + (typeof window !== 'undefined' && + window.document && window.document.createElement) ); /** @@ -6680,9 +6784,100 @@ var ExecutionEnvironment = { module.exports = ExecutionEnvironment; -},{}],65:[function(require,module,exports){ +},{}],61:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule FallbackCompositionState + * @typechecks static-only + */ + +'use strict'; + +var PooledClass = require("./PooledClass"); + +var assign = require("./Object.assign"); +var getTextContentAccessor = require("./getTextContentAccessor"); + +/** + * This helper class stores information about text content of a target node, + * allowing comparison of content before and after a given event. + * + * Identify the node where selection currently begins, then observe + * both its text content and its current position in the DOM. Since the + * browser may natively replace the target node during composition, we can + * use its position to find its replacement. + * + * @param {DOMEventTarget} root + */ +function FallbackCompositionState(root) { + this._root = root; + this._startText = this.getText(); + this._fallbackText = null; +} + +assign(FallbackCompositionState.prototype, { + /** + * Get current text of input. + * + * @return {string} + */ + getText: function() { + if ('value' in this._root) { + return this._root.value; + } + return this._root[getTextContentAccessor()]; + }, + + /** + * Determine the differing substring between the initially stored + * text content and the current content. + * + * @return {string} + */ + getData: function() { + if (this._fallbackText) { + return this._fallbackText; + } + + var start; + var startValue = this._startText; + var startLength = startValue.length; + var end; + var endValue = this.getText(); + var endLength = endValue.length; + + for (start = 0; start < startLength; start++) { + if (startValue[start] !== endValue[start]) { + break; + } + } + + var minEnd = startLength - start; + for (end = 1; end <= minEnd; end++) { + if (startValue[startLength - end] !== endValue[endLength - end]) { + break; + } + } + + var sliceTail = end > 1 ? 1 - end : undefined; + this._fallbackText = endValue.slice(start, sliceTail); + return this._fallbackText; + } +}); + +PooledClass.addPoolingTo(FallbackCompositionState); + +module.exports = FallbackCompositionState; + +},{"./Object.assign":67,"./PooledClass":68,"./getTextContentAccessor":184}],62:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6694,7 +6889,7 @@ module.exports = ExecutionEnvironment; /*jslint bitwise: true*/ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -6771,8 +6966,13 @@ var HTMLDOMPropertyConfig = { draggable: null, encType: null, form: MUST_USE_ATTRIBUTE, + formAction: MUST_USE_ATTRIBUTE, + formEncType: MUST_USE_ATTRIBUTE, + formMethod: MUST_USE_ATTRIBUTE, formNoValidate: HAS_BOOLEAN_VALUE, + formTarget: MUST_USE_ATTRIBUTE, frameBorder: MUST_USE_ATTRIBUTE, + headers: null, height: MUST_USE_ATTRIBUTE, hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, href: null, @@ -6786,6 +6986,8 @@ var HTMLDOMPropertyConfig = { list: MUST_USE_ATTRIBUTE, loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, manifest: MUST_USE_ATTRIBUTE, + marginHeight: null, + marginWidth: null, max: null, maxLength: MUST_USE_ATTRIBUTE, media: MUST_USE_ATTRIBUTE, @@ -6796,7 +6998,7 @@ var HTMLDOMPropertyConfig = { muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, name: null, noValidate: HAS_BOOLEAN_VALUE, - open: null, + open: HAS_BOOLEAN_VALUE, pattern: null, placeholder: null, poster: null, @@ -6836,12 +7038,22 @@ var HTMLDOMPropertyConfig = { /** * 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 + // autoCapitalize and autoCorrect are supported in Mobile Safari for + // keyboard hints. + autoCapitalize: null, + autoCorrect: null, + // itemProp, itemScope, itemType are for + // Microdata support. See http://schema.org/docs/gs.html + itemProp: MUST_USE_ATTRIBUTE, + itemScope: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, + itemType: MUST_USE_ATTRIBUTE, + // itemID and itemRef are for Microdata support as well but + // only specified in the the WHATWG spec document. See + // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api + itemID: MUST_USE_ATTRIBUTE, + itemRef: MUST_USE_ATTRIBUTE, + // property is supported for OpenGraph in meta tags. + property: null }, DOMAttributeNames: { acceptCharset: 'accept-charset', @@ -6855,7 +7067,9 @@ var HTMLDOMPropertyConfig = { autoCorrect: 'autocorrect', autoFocus: 'autofocus', autoPlay: 'autoplay', - encType: 'enctype', + // `encoding` is equivalent to `enctype`, IE8 lacks an `enctype` setter. + // http://www.w3.org/TR/html5/forms.html#dom-fs-encoding + encType: 'encoding', hrefLang: 'hreflang', radioGroup: 'radiogroup', spellCheck: 'spellcheck', @@ -6866,9 +7080,9 @@ var HTMLDOMPropertyConfig = { module.exports = HTMLDOMPropertyConfig; -},{"./DOMProperty":53,"./ExecutionEnvironment":64}],66:[function(require,module,exports){ +},{"./DOMProperty":49,"./ExecutionEnvironment":60}],63:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6879,7 +7093,7 @@ module.exports = HTMLDOMPropertyConfig; * @typechecks static-only */ -"use strict"; +'use strict'; var ReactLink = require("./ReactLink"); var ReactStateSetters = require("./ReactStateSetters"); @@ -6907,10 +7121,10 @@ var LinkedStateMixin = { module.exports = LinkedStateMixin; -},{"./ReactLink":109,"./ReactStateSetters":126}],67:[function(require,module,exports){ +},{"./ReactLink":113,"./ReactStateSetters":132}],64:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -6921,7 +7135,7 @@ module.exports = LinkedStateMixin; * @typechecks static-only */ -"use strict"; +'use strict'; var ReactPropTypes = require("./ReactPropTypes"); @@ -6992,7 +7206,7 @@ var LinkedValueUtils = { props.onChange || props.readOnly || props.disabled) { - return; + return null; } return new Error( 'You provided a `value` prop to a form field without an ' + @@ -7006,7 +7220,7 @@ var LinkedValueUtils = { props.onChange || props.readOnly || props.disabled) { - return; + return null; } return new Error( 'You provided a `checked` prop to a form field without an ' + @@ -7063,10 +7277,10 @@ var LinkedValueUtils = { module.exports = LinkedValueUtils; }).call(this,require('_process')) -},{"./ReactPropTypes":120,"./invariant":182,"_process":1}],68:[function(require,module,exports){ +},{"./ReactPropTypes":124,"./invariant":189,"_process":1}],65:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7076,7 +7290,7 @@ module.exports = LinkedValueUtils; * @providesModule LocalEventTrapMixin */ -"use strict"; +'use strict'; var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); @@ -7091,10 +7305,17 @@ function remove(event) { var LocalEventTrapMixin = { trapBubbledEvent:function(topLevelType, handlerBaseName) { ("production" !== process.env.NODE_ENV ? invariant(this.isMounted(), 'Must be mounted to trap events') : invariant(this.isMounted())); + // If a component renders to null or if another component fatals and causes + // the state of the tree to be corrupted, `node` here can be null. + var node = this.getDOMNode(); + ("production" !== process.env.NODE_ENV ? invariant( + node, + 'LocalEventTrapMixin.trapBubbledEvent(...): Requires node to be rendered.' + ) : invariant(node)); var listener = ReactBrowserEventEmitter.trapBubbledEvent( topLevelType, handlerBaseName, - this.getDOMNode() + node ); this._localEventListeners = accumulateInto(this._localEventListeners, listener); @@ -7113,9 +7334,9 @@ var LocalEventTrapMixin = { module.exports = LocalEventTrapMixin; }).call(this,require('_process')) -},{"./ReactBrowserEventEmitter":74,"./accumulateInto":151,"./forEachAccumulated":168,"./invariant":182,"_process":1}],69:[function(require,module,exports){ +},{"./ReactBrowserEventEmitter":71,"./accumulateInto":157,"./forEachAccumulated":174,"./invariant":189,"_process":1}],66:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7126,7 +7347,7 @@ module.exports = LocalEventTrapMixin; * @typechecks static-only */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); @@ -7171,9 +7392,9 @@ var MobileSafariClickEventPlugin = { module.exports = MobileSafariClickEventPlugin; -},{"./EventConstants":58,"./emptyFunction":163}],70:[function(require,module,exports){ +},{"./EventConstants":54,"./emptyFunction":168}],67:[function(require,module,exports){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7185,6 +7406,8 @@ module.exports = MobileSafariClickEventPlugin; // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign +'use strict'; + function assign(target, sources) { if (target == null) { throw new TypeError('Object.assign target cannot be null or undefined'); @@ -7214,14 +7437,14 @@ function assign(target, sources) { } return to; -}; +} module.exports = assign; -},{}],71:[function(require,module,exports){ +},{}],68:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7231,7 +7454,7 @@ module.exports = assign; * @providesModule PooledClass */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -7334,10 +7557,10 @@ var PooledClass = { module.exports = PooledClass; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],72:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],69:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7347,51 +7570,44 @@ module.exports = PooledClass; * @providesModule React */ -"use strict"; +/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/ + +'use strict'; -var DOMPropertyOperations = require("./DOMPropertyOperations"); var EventPluginUtils = require("./EventPluginUtils"); var ReactChildren = require("./ReactChildren"); var ReactComponent = require("./ReactComponent"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactContext = require("./ReactContext"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactElement = require("./ReactElement"); var ReactElementValidator = require("./ReactElementValidator"); var ReactDOM = require("./ReactDOM"); -var ReactDOMComponent = require("./ReactDOMComponent"); +var ReactDOMTextComponent = require("./ReactDOMTextComponent"); var ReactDefaultInjection = require("./ReactDefaultInjection"); var ReactInstanceHandles = require("./ReactInstanceHandles"); -var ReactLegacyElement = require("./ReactLegacyElement"); var ReactMount = require("./ReactMount"); -var ReactMultiChild = require("./ReactMultiChild"); var ReactPerf = require("./ReactPerf"); var ReactPropTypes = require("./ReactPropTypes"); +var ReactReconciler = require("./ReactReconciler"); var ReactServerRendering = require("./ReactServerRendering"); -var ReactTextComponent = require("./ReactTextComponent"); var assign = require("./Object.assign"); -var deprecated = require("./deprecated"); +var findDOMNode = require("./findDOMNode"); var onlyChild = require("./onlyChild"); ReactDefaultInjection.inject(); var createElement = ReactElement.createElement; var createFactory = ReactElement.createFactory; +var cloneElement = ReactElement.cloneElement; if ("production" !== process.env.NODE_ENV) { createElement = ReactElementValidator.createElement; createFactory = ReactElementValidator.createFactory; + cloneElement = ReactElementValidator.cloneElement; } -// TODO: Drop legacy elements once classes no longer export these factories -createElement = ReactLegacyElement.wrapCreateElement( - createElement -); -createFactory = ReactLegacyElement.wrapCreateFactory( - createFactory -); - var render = ReactPerf.measure('React', 'render', ReactMount.render); var React = { @@ -7401,56 +7617,32 @@ var React = { count: ReactChildren.count, only: onlyChild }, + Component: ReactComponent, DOM: ReactDOM, PropTypes: ReactPropTypes, initializeTouchEvents: function(shouldUseTouch) { EventPluginUtils.useTouchEvents = shouldUseTouch; }, - createClass: ReactCompositeComponent.createClass, + createClass: ReactClass.createClass, createElement: createElement, + cloneElement: cloneElement, createFactory: createFactory, + createMixin: function(mixin) { + // Currently a noop. Will be used to validate and trace mixins. + return mixin; + }, constructAndRenderComponent: ReactMount.constructAndRenderComponent, constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, + findDOMNode: findDOMNode, render: render, renderToString: ReactServerRendering.renderToString, renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup, unmountComponentAtNode: ReactMount.unmountComponentAtNode, - isValidClass: ReactLegacyElement.isValidClass, isValidElement: ReactElement.isValidElement, withContext: ReactContext.withContext, // Hook for JSX spread, don't use this for anything else. - __spread: assign, - - // Deprecations (remove for 0.13) - renderComponent: deprecated( - 'React', - 'renderComponent', - 'render', - this, - render - ), - renderComponentToString: deprecated( - 'React', - 'renderComponentToString', - 'renderToString', - this, - ReactServerRendering.renderToString - ), - renderComponentToStaticMarkup: deprecated( - 'React', - 'renderComponentToStaticMarkup', - 'renderToStaticMarkup', - this, - ReactServerRendering.renderToStaticMarkup - ), - isValidComponent: deprecated( - 'React', - 'isValidComponent', - 'isValidElement', - this, - ReactElement.isValidElement - ) + __spread: assign }; // Inject the runtime into a devtools global hook regardless of browser. @@ -7459,14 +7651,11 @@ if ( typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') { __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ - Component: ReactComponent, CurrentOwner: ReactCurrentOwner, - DOMComponent: ReactDOMComponent, - DOMPropertyOperations: DOMPropertyOperations, InstanceHandles: ReactInstanceHandles, Mount: ReactMount, - MultiChild: ReactMultiChild, - TextComponent: ReactTextComponent + Reconciler: ReactReconciler, + TextComponent: ReactDOMTextComponent }); } @@ -7515,17 +7704,14 @@ if ("production" !== process.env.NODE_ENV) { } } -// Version exists only in the open-source version of React, not in Facebook's -// internal version. -React.version = '0.12.0'; +React.version = '0.13.1'; module.exports = React; }).call(this,require('_process')) -},{"./DOMPropertyOperations":54,"./EventPluginUtils":62,"./ExecutionEnvironment":64,"./Object.assign":70,"./ReactChildren":77,"./ReactComponent":78,"./ReactCompositeComponent":81,"./ReactContext":82,"./ReactCurrentOwner":83,"./ReactDOM":84,"./ReactDOMComponent":86,"./ReactDefaultInjection":96,"./ReactElement":99,"./ReactElementValidator":100,"./ReactInstanceHandles":107,"./ReactLegacyElement":108,"./ReactMount":111,"./ReactMultiChild":112,"./ReactPerf":116,"./ReactPropTypes":120,"./ReactServerRendering":124,"./ReactTextComponent":128,"./deprecated":162,"./onlyChild":193,"_process":1}],73:[function(require,module,exports){ -(function (process){ +},{"./EventPluginUtils":58,"./ExecutionEnvironment":60,"./Object.assign":67,"./ReactChildren":75,"./ReactClass":76,"./ReactComponent":77,"./ReactContext":82,"./ReactCurrentOwner":83,"./ReactDOM":84,"./ReactDOMTextComponent":95,"./ReactDefaultInjection":98,"./ReactElement":101,"./ReactElementValidator":102,"./ReactInstanceHandles":110,"./ReactMount":115,"./ReactPerf":120,"./ReactPropTypes":124,"./ReactReconciler":127,"./ReactServerRendering":130,"./findDOMNode":171,"./onlyChild":199,"_process":1}],70:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7535,12 +7721,9 @@ module.exports = React; * @providesModule ReactBrowserComponentMixin */ -"use strict"; - -var ReactEmptyComponent = require("./ReactEmptyComponent"); -var ReactMount = require("./ReactMount"); +'use strict'; -var invariant = require("./invariant"); +var findDOMNode = require("./findDOMNode"); var ReactBrowserComponentMixin = { /** @@ -7551,23 +7734,15 @@ var ReactBrowserComponentMixin = { * @protected */ getDOMNode: function() { - ("production" !== process.env.NODE_ENV ? 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); + return findDOMNode(this); } }; module.exports = ReactBrowserComponentMixin; -}).call(this,require('_process')) -},{"./ReactEmptyComponent":101,"./ReactMount":111,"./invariant":182,"_process":1}],74:[function(require,module,exports){ +},{"./findDOMNode":171}],71:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7578,7 +7753,7 @@ module.exports = ReactBrowserComponentMixin; * @typechecks static-only */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPluginHub = require("./EventPluginHub"); @@ -7694,7 +7869,7 @@ var topEventMapping = { /** * To ensure no conflicts with other potential React instances on the page */ -var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2); +var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2); function getListeningForDocument(mountAt) { // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` @@ -7751,8 +7926,7 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { */ isEnabled: function() { return !!( - ReactBrowserEventEmitter.ReactEventListener && - ReactBrowserEventEmitter.ReactEventListener.isEnabled() + (ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled()) ); }, @@ -7787,8 +7961,7 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { for (var i = 0, l = dependencies.length; i < l; i++) { var dependency = dependencies[i]; if (!( - isListening.hasOwnProperty(dependency) && - isListening[dependency] + (isListening.hasOwnProperty(dependency) && isListening[dependency]) )) { if (dependency === topLevelTypes.topWheel) { if (isEventSupported('wheel')) { @@ -7896,7 +8069,7 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { * * @see http://www.quirksmode.org/dom/events/scroll.html */ - ensureScrollValueMonitoring: function(){ + ensureScrollValueMonitoring: function() { if (!isMonitoringScrollValue) { var refresh = ViewportMetrics.refreshScrollValues; ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh); @@ -7920,9 +8093,9 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { module.exports = ReactBrowserEventEmitter; -},{"./EventConstants":58,"./EventPluginHub":60,"./EventPluginRegistry":61,"./Object.assign":70,"./ReactEventEmitterMixin":103,"./ViewportMetrics":150,"./isEventSupported":183}],75:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPluginHub":56,"./EventPluginRegistry":57,"./Object.assign":67,"./ReactEventEmitterMixin":105,"./ViewportMetrics":156,"./isEventSupported":190}],72:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7933,7 +8106,7 @@ module.exports = ReactBrowserEventEmitter; * @providesModule ReactCSSTransitionGroup */ -"use strict"; +'use strict'; var React = require("./React"); @@ -7951,12 +8124,14 @@ var ReactCSSTransitionGroup = React.createClass({ propTypes: { transitionName: React.PropTypes.string.isRequired, + transitionAppear: React.PropTypes.bool, transitionEnter: React.PropTypes.bool, transitionLeave: React.PropTypes.bool }, getDefaultProps: function() { return { + transitionAppear: false, transitionEnter: true, transitionLeave: true }; @@ -7969,6 +8144,7 @@ var ReactCSSTransitionGroup = React.createClass({ return ReactCSSTransitionGroupChild( { name: this.props.transitionName, + appear: this.props.transitionAppear, enter: this.props.transitionEnter, leave: this.props.transitionLeave }, @@ -7987,10 +8163,10 @@ var ReactCSSTransitionGroup = React.createClass({ module.exports = ReactCSSTransitionGroup; -},{"./Object.assign":70,"./React":72,"./ReactCSSTransitionGroupChild":76,"./ReactTransitionGroup":131}],76:[function(require,module,exports){ +},{"./Object.assign":67,"./React":69,"./ReactCSSTransitionGroupChild":73,"./ReactTransitionGroup":136}],73:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -8001,7 +8177,7 @@ module.exports = ReactCSSTransitionGroup; * @providesModule ReactCSSTransitionGroupChild */ -"use strict"; +'use strict'; var React = require("./React"); @@ -8009,6 +8185,7 @@ var CSSCore = require("./CSSCore"); var ReactTransitionEvents = require("./ReactTransitionEvents"); var onlyChild = require("./onlyChild"); +var warning = require("./warning"); // We don't remove the element from the DOM until we receive an animationend or // transitionend event. If the user screws up and forgets to add an animation @@ -8022,12 +8199,14 @@ var noEventListener = null; if ("production" !== process.env.NODE_ENV) { noEventListener = function() { - console.warn( + ("production" !== process.env.NODE_ENV ? warning( + false, 'transition(): tried to perform an animation without ' + '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.' - ); + '%sms). You should either disable this ' + + 'transition in JS or add a CSS animation/transition.', + NO_EVENT_TIMEOUT + ) : null); }; } @@ -8055,7 +8234,9 @@ var ReactCSSTransitionGroupChild = React.createClass({ // Usually this optional callback is used for informing an owner of // a leave animation and telling it to remove the child. - finishCallback && finishCallback(); + if (finishCallback) { + finishCallback(); + } }; ReactTransitionEvents.addEndEventListener(node, endListener); @@ -8098,6 +8279,14 @@ var ReactCSSTransitionGroupChild = React.createClass({ } }, + componentWillAppear: function(done) { + if (this.props.appear) { + this.transition('appear', done); + } else { + done(); + } + }, + componentWillEnter: function(done) { if (this.props.enter) { this.transition('enter', done); @@ -8122,10 +8311,137 @@ var ReactCSSTransitionGroupChild = React.createClass({ module.exports = ReactCSSTransitionGroupChild; }).call(this,require('_process')) -},{"./CSSCore":45,"./React":72,"./ReactTransitionEvents":130,"./onlyChild":193,"_process":1}],77:[function(require,module,exports){ +},{"./CSSCore":42,"./React":69,"./ReactTransitionEvents":135,"./onlyChild":199,"./warning":210,"_process":1}],74:[function(require,module,exports){ +/** + * Copyright 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildReconciler + * @typechecks static-only + */ + +'use strict'; + +var ReactReconciler = require("./ReactReconciler"); + +var flattenChildren = require("./flattenChildren"); +var instantiateReactComponent = require("./instantiateReactComponent"); +var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); + +/** + * ReactChildReconciler provides helpers for initializing or updating a set of + * children. Its output is suitable for passing it onto ReactMultiChild which + * does diffed reordering and insertion. + */ +var ReactChildReconciler = { + + /** + * Generates a "mount image" for each of the supplied children. In the case + * of `ReactDOMComponent`, a mount image is a string of markup. + * + * @param {?object} nestedChildNodes Nested child maps. + * @return {?object} A set of child instances. + * @internal + */ + instantiateChildren: function(nestedChildNodes, transaction, context) { + var children = flattenChildren(nestedChildNodes); + for (var name in children) { + if (children.hasOwnProperty(name)) { + var child = children[name]; + // The rendered children must be turned into instances as they're + // mounted. + var childInstance = instantiateReactComponent(child, null); + children[name] = childInstance; + } + } + return children; + }, + + /** + * Updates the rendered children and returns a new set of children. + * + * @param {?object} prevChildren Previously initialized set of children. + * @param {?object} nextNestedChildNodes Nested child maps. + * @param {ReactReconcileTransaction} transaction + * @param {object} context + * @return {?object} A new set of child instances. + * @internal + */ + updateChildren: function( + prevChildren, + nextNestedChildNodes, + transaction, + context) { + // We currently don't have a way to track moves here but if we use iterators + // instead of for..in we can zip the iterators and check if an item has + // moved. + // TODO: If nothing has changed, return the prevChildren object so that we + // can quickly bailout if nothing has changed. + var nextChildren = flattenChildren(nextNestedChildNodes); + if (!nextChildren && !prevChildren) { + return null; + } + var name; + for (name in nextChildren) { + if (!nextChildren.hasOwnProperty(name)) { + continue; + } + var prevChild = prevChildren && prevChildren[name]; + var prevElement = prevChild && prevChild._currentElement; + var nextElement = nextChildren[name]; + if (shouldUpdateReactComponent(prevElement, nextElement)) { + ReactReconciler.receiveComponent( + prevChild, nextElement, transaction, context + ); + nextChildren[name] = prevChild; + } else { + if (prevChild) { + ReactReconciler.unmountComponent(prevChild, name); + } + // The child must be instantiated before it's mounted. + var nextChildInstance = instantiateReactComponent( + nextElement, + null + ); + nextChildren[name] = nextChildInstance; + } + } + // Unmount children that are no longer present. + for (name in prevChildren) { + if (prevChildren.hasOwnProperty(name) && + !(nextChildren && nextChildren.hasOwnProperty(name))) { + ReactReconciler.unmountComponent(prevChildren[name]); + } + } + return nextChildren; + }, + + /** + * Unmounts all rendered children. This should be used to clean up children + * when this component is unmounted. + * + * @param {?object} renderedChildren Previously initialized set of children. + * @internal + */ + unmountChildren: function(renderedChildren) { + for (var name in renderedChildren) { + var renderedChild = renderedChildren[name]; + ReactReconciler.unmountComponent(renderedChild); + } + } + +}; + +module.exports = ReactChildReconciler; + +},{"./ReactReconciler":127,"./flattenChildren":172,"./instantiateReactComponent":188,"./shouldUpdateReactComponent":206}],75:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -8135,9 +8451,10 @@ module.exports = ReactCSSTransitionGroupChild; * @providesModule ReactChildren */ -"use strict"; +'use strict'; var PooledClass = require("./PooledClass"); +var ReactFragment = require("./ReactFragment"); var traverseAllChildren = require("./traverseAllChildren"); var warning = require("./warning"); @@ -8207,13 +8524,15 @@ function mapSingleChildIntoContext(traverseContext, child, name, i) { var mapResult = mapBookKeeping.mapResult; var keyUnique = !mapResult.hasOwnProperty(name); - ("production" !== process.env.NODE_ENV ? warning( - keyUnique, - 'ReactChildren.map(...): Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, only ' + - 'the first child will be used.', - name - ) : null); + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + keyUnique, + 'ReactChildren.map(...): Encountered two children with the same key, ' + + '`%s`. Child keys must be unique; when two children share a key, only ' + + 'the first child will be used.', + name + ) : null); + } if (keyUnique) { var mappedChild = @@ -8245,7 +8564,7 @@ function mapChildren(children, func, context) { var traverseContext = MapBookKeeping.getPooled(mapResult, func, context); traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); MapBookKeeping.release(traverseContext); - return mapResult; + return ReactFragment.create(mapResult); } function forEachSingleChildDummy(traverseContext, child, name, i) { @@ -8272,664 +8591,41 @@ var ReactChildren = { module.exports = ReactChildren; }).call(this,require('_process')) -},{"./PooledClass":71,"./traverseAllChildren":200,"./warning":202,"_process":1}],78:[function(require,module,exports){ -(function (process){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ReactComponent - */ - -"use strict"; - -var ReactElement = require("./ReactElement"); -var ReactOwner = require("./ReactOwner"); -var ReactUpdates = require("./ReactUpdates"); - -var assign = require("./Object.assign"); -var invariant = require("./invariant"); -var keyMirror = require("./keyMirror"); - -/** - * 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 -}); - -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 - */ -var unmountIDFromEnvironment = null; - -/** - * The "image" of a component tree, is the platform specific (typically - * serialized) data that represents a tree of lower level UI building blocks. - * On the web, this "image" is HTML markup which describes a construction of - * low level `div` and `span` nodes. Other platforms may have different - * encoding of this "image". This must be injected. - * - * @private - */ -var mountImageIntoNode = null; - -/** - * 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: - * - * `mountComponent` - * Initializes the component, renders markup, and registers event listeners. - * - * `receiveComponent` - * Updates the rendered DOM nodes to match the given component. - * - * `unmountComponent` - * Releases any resources allocated by this component. - * - * Components can also be "owned" by other components. Being owned by another - * component means being constructed by that component. This is different from - * being the child of a component, which means having a DOM representation that - * is a child of the DOM representation of that component. - * - * @class ReactComponent - */ -var ReactComponent = { - - injection: { - injectEnvironment: function(ReactComponentEnvironment) { - ("production" !== process.env.NODE_ENV ? invariant( - !injected, - 'ReactComponent: injectEnvironment() can only be called once.' - ) : invariant(!injected)); - mountImageIntoNode = ReactComponentEnvironment.mountImageIntoNode; - unmountIDFromEnvironment = - ReactComponentEnvironment.unmountIDFromEnvironment; - ReactComponent.BackendIDOperations = - ReactComponentEnvironment.BackendIDOperations; - injected = true; - } - }, - - /** - * @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, - - /** - * Base functionality for every ReactComponent constructor. Mixed into the - * `ReactComponent` prototype, but exposed statically for easy access. - * - * @lends {ReactComponent.prototype} - */ - Mixin: { - - /** - * Checks whether or not this component is mounted. - * - * @return {boolean} True if mounted, false otherwise. - * @final - * @protected - */ - isMounted: function() { - return this._lifeCycleState === ComponentLifeCycle.MOUNTED; - }, - - /** - * 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 the pending element if it exists, otherwise with existing - // element props. - var element = this._pendingElement || this._currentElement; - this.replaceProps( - assign({}, element.props, partialProps), - callback - ); - }, - - /** - * Replaces all of the props. - * - * @param {object} props New props. - * @param {?function} callback Called after props are updated. - * @final - * @public - */ - replaceProps: function(props, callback) { - ("production" !== process.env.NODE_ENV ? invariant( - this.isMounted(), - 'replaceProps(...): Can only update a mounted component.' - ) : invariant(this.isMounted())); - ("production" !== process.env.NODE_ENV ? 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 is a deoptimized path. We optimize for always having a element. - // This creates an extra internal element. - this._pendingElement = ReactElement.cloneAndReplaceProps( - this._pendingElement || this._currentElement, - 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 element. - // This creates an extra internal element. - var element = this._pendingElement || this._currentElement; - this._pendingElement = ReactElement.cloneAndReplaceProps( - element, - assign({}, element.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 {ReactElement} element - * @internal - */ - construct: function(element) { - // This is the public exposed props object after it has been processed - // with default props. The element's props represents the true internal - // state of the props. - this.props = element.props; - // Record the component responsible for creating this component. - // This is accessible through the element 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 = element._owner; - - // All components start unmounted. - this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; - - // See ReactUpdates. - this._pendingCallbacks = null; - - // We keep the old element and a reference to the pending element - // to track updates. - this._currentElement = element; - this._pendingElement = 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 - * `ReactComponent.Mixin.mountComponent.call(this, ...)`. - * - * @param {string} rootID DOM ID of the root node. - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy. - * @return {?string} Rendered markup to be inserted into the DOM. - * @internal - */ - mountComponent: function(rootID, transaction, mountDepth) { - ("production" !== process.env.NODE_ENV ? 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 ref = this._currentElement.ref; - if (ref != null) { - var owner = this._currentElement._owner; - ReactOwner.addComponentAsRefTo(this, ref, owner); - } - this._rootNodeID = rootID; - this._lifeCycleState = ComponentLifeCycle.MOUNTED; - this._mountDepth = mountDepth; - // Effectively: return ''; - }, - - /** - * Releases any resources allocated by `mountComponent`. - * - * NOTE: This does not remove any nodes from the DOM. - * - * Subclasses that override this method should make sure to invoke - * `ReactComponent.Mixin.unmountComponent.call(this)`. - * - * @internal - */ - unmountComponent: function() { - ("production" !== process.env.NODE_ENV ? invariant( - this.isMounted(), - 'unmountComponent(): Can only unmount a mounted component.' - ) : invariant(this.isMounted())); - var ref = this._currentElement.ref; - if (ref != null) { - ReactOwner.removeComponentAsRefFrom(this, ref, this._owner); - } - unmountIDFromEnvironment(this._rootNodeID); - this._rootNodeID = null; - this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; - }, - - /** - * Given a new instance of this component, updates the rendered DOM nodes - * as if that instance was rendered instead. - * - * 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(nextElement, transaction) { - ("production" !== process.env.NODE_ENV ? invariant( - this.isMounted(), - 'receiveComponent(...): Can only update a mounted component.' - ) : invariant(this.isMounted())); - this._pendingElement = nextElement; - this.performUpdateIfNecessary(transaction); - }, - - /** - * If `_pendingElement` is set, update the component. - * - * @param {ReactReconcileTransaction} transaction - * @internal - */ - performUpdateIfNecessary: function(transaction) { - if (this._pendingElement == null) { - return; - } - var prevElement = this._currentElement; - var nextElement = this._pendingElement; - this._currentElement = nextElement; - this.props = nextElement.props; - this._owner = nextElement._owner; - this._pendingElement = null; - this.updateComponent(transaction, prevElement); - }, - - /** - * Updates the component's currently mounted representation. - * - * @param {ReactReconcileTransaction} transaction - * @param {object} prevElement - * @internal - */ - updateComponent: function(transaction, prevElement) { - var nextElement = this._currentElement; - - // 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`. We use the element instead - // of the public this.props because the post processing cannot determine - // a ref. The ref conceptually lives on the element. - - // 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 (nextElement._owner !== prevElement._owner || - nextElement.ref !== prevElement.ref) { - if (prevElement.ref != null) { - ReactOwner.removeComponentAsRefFrom( - this, prevElement.ref, prevElement._owner - ); - } - // Correct, even if the owner is the same, and only the ref has changed. - if (nextElement.ref != null) { - ReactOwner.addComponentAsRefTo( - this, - nextElement.ref, - nextElement._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.render} - */ - mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); - transaction.perform( - this._mountComponentIntoNode, - this, - rootID, - container, - transaction, - shouldReuseMarkup - ); - 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 - * @private - */ - _mountComponentIntoNode: function( - rootID, - container, - transaction, - shouldReuseMarkup) { - var markup = this.mountComponent(rootID, transaction, 0); - mountImageIntoNode(markup, container, shouldReuseMarkup); - }, - - /** - * Checks if this component is owned by the supplied `owner` component. - * - * @param {ReactComponent} owner Component to check. - * @return {boolean} True if `owners` owns this component. - * @final - * @internal - */ - isOwnedBy: function(owner) { - return this._owner === owner; - }, - - /** - * Gets another component, that shares the same owner as this one, by ref. - * - * @param {string} ref of a sibling Component. - * @return {?ReactComponent} the actual sibling Component. - * @final - * @internal - */ - getSiblingByRef: function(ref) { - var owner = this._owner; - if (!owner || !owner.refs) { - return null; - } - return owner.refs[ref]; - } - } -}; - -module.exports = ReactComponent; - -}).call(this,require('_process')) -},{"./Object.assign":70,"./ReactElement":99,"./ReactOwner":115,"./ReactUpdates":132,"./invariant":182,"./keyMirror":188,"_process":1}],79:[function(require,module,exports){ +},{"./PooledClass":68,"./ReactFragment":107,"./traverseAllChildren":208,"./warning":210,"_process":1}],76:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule ReactComponentBrowserEnvironment + * @providesModule ReactClass */ -/*jslint evil: true */ - -"use strict"; - -var ReactDOMIDOperations = require("./ReactDOMIDOperations"); -var ReactMarkupChecksum = require("./ReactMarkupChecksum"); -var ReactMount = require("./ReactMount"); -var ReactPerf = require("./ReactPerf"); -var ReactReconcileTransaction = require("./ReactReconcileTransaction"); - -var getReactRootElementInContainer = require("./getReactRootElementInContainer"); -var invariant = require("./invariant"); -var setInnerHTML = require("./setInnerHTML"); - - -var ELEMENT_NODE_TYPE = 1; -var DOC_NODE_TYPE = 9; - - -/** - * Abstracts away all functionality of `ReactComponent` requires knowledge of - * the browser context. - */ -var ReactComponentBrowserEnvironment = { - ReactReconcileTransaction: ReactReconcileTransaction, - - BackendIDOperations: ReactDOMIDOperations, - - /** - * If a particular environment requires that some resources be cleaned up, - * specify this in the injected Mixin. In the DOM, we would likely want to - * purge any cached node ID lookups. - * - * @private - */ - unmountIDFromEnvironment: function(rootNodeID) { - ReactMount.purgeID(rootNodeID); - }, - - /** - * @param {string} markup Markup string to place into the DOM Element. - * @param {DOMElement} container DOM Element to insert markup into. - * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the - * container if possible. - */ - mountImageIntoNode: ReactPerf.measure( - 'ReactComponentBrowserEnvironment', - 'mountImageIntoNode', - function(markup, container, shouldReuseMarkup) { - ("production" !== process.env.NODE_ENV ? invariant( - container && ( - container.nodeType === ELEMENT_NODE_TYPE || - container.nodeType === DOC_NODE_TYPE - ), - 'mountComponentIntoNode(...): Target container is not valid.' - ) : invariant(container && ( - container.nodeType === ELEMENT_NODE_TYPE || - container.nodeType === DOC_NODE_TYPE - ))); - - if (shouldReuseMarkup) { - if (ReactMarkupChecksum.canReuseMarkup( - markup, - getReactRootElementInContainer(container))) { - return; - } else { - ("production" !== process.env.NODE_ENV ? invariant( - container.nodeType !== DOC_NODE_TYPE, - 'You\'re trying to render a component to the document using ' + - 'server rendering but the checksum was invalid. This usually ' + - 'means you rendered a different component type or props on ' + - 'the client from the one on the server, or your render() ' + - 'methods are impure. React cannot handle this case due to ' + - 'cross-browser quirks by rendering at the document root. You ' + - 'should look for environment dependent code in your components ' + - 'and ensure the props are the same client and server side.' - ) : invariant(container.nodeType !== DOC_NODE_TYPE)); - - if ("production" !== process.env.NODE_ENV) { - 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 ' + - '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.' - ); - } - } - } - - ("production" !== process.env.NODE_ENV ? 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)); - - setInnerHTML(container, markup); - } - ) -}; - -module.exports = ReactComponentBrowserEnvironment; - -}).call(this,require('_process')) -},{"./ReactDOMIDOperations":88,"./ReactMarkupChecksum":110,"./ReactMount":111,"./ReactPerf":116,"./ReactReconcileTransaction":122,"./getReactRootElementInContainer":176,"./invariant":182,"./setInnerHTML":196,"_process":1}],80:[function(require,module,exports){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * -* @providesModule ReactComponentWithPureRenderMixin -*/ - -"use strict"; - -var shallowEqual = require("./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":197}],81:[function(require,module,exports){ -(function (process){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ReactCompositeComponent - */ - -"use strict"; +'use strict'; var ReactComponent = require("./ReactComponent"); -var ReactContext = require("./ReactContext"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactElement = require("./ReactElement"); -var ReactElementValidator = require("./ReactElementValidator"); -var ReactEmptyComponent = require("./ReactEmptyComponent"); var ReactErrorUtils = require("./ReactErrorUtils"); -var ReactLegacyElement = require("./ReactLegacyElement"); -var ReactOwner = require("./ReactOwner"); -var ReactPerf = require("./ReactPerf"); -var ReactPropTransferer = require("./ReactPropTransferer"); +var ReactInstanceMap = require("./ReactInstanceMap"); +var ReactLifeCycle = require("./ReactLifeCycle"); var ReactPropTypeLocations = require("./ReactPropTypeLocations"); var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames"); -var ReactUpdates = require("./ReactUpdates"); +var ReactUpdateQueue = require("./ReactUpdateQueue"); var assign = require("./Object.assign"); -var instantiateReactComponent = require("./instantiateReactComponent"); var invariant = require("./invariant"); var keyMirror = require("./keyMirror"); var keyOf = require("./keyOf"); -var monitorCodeUse = require("./monitorCodeUse"); -var mapObject = require("./mapObject"); -var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); var warning = require("./warning"); var MIXINS_KEY = keyOf({mixins: null}); /** - * Policies that describe methods in `ReactCompositeComponentInterface`. + * Policies that describe methods in `ReactClassInterface`. */ var SpecPolicy = keyMirror({ /** @@ -8942,7 +8638,7 @@ var SpecPolicy = keyMirror({ */ DEFINE_MANY: null, /** - * These methods are overriding the base ReactCompositeComponent class. + * These methods are overriding the base class. */ OVERRIDE_BASE: null, /** @@ -8960,7 +8656,7 @@ var injectedMixins = []; * Composite components are higher-level components that compose other composite * or native components. * - * To create a new type of `ReactCompositeComponent`, pass a specification of + * To create a new type of `ReactClass`, pass a specification of * your new class to `React.createClass`. The only requirement of your class * specification is that you implement a `render` method. * @@ -8971,14 +8667,14 @@ var injectedMixins = []; * }); * * The class specification supports a specific protocol of methods that have - * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for + * special meaning (e.g. `render`). See `ReactClassInterface` for * more the comprehensive protocol. Any other properties and methods in the * class specification will available on the prototype. * - * @interface ReactCompositeComponentInterface + * @interface ReactClassInterface * @internal */ -var ReactCompositeComponentInterface = { +var ReactClassInterface = { /** * An array of Mixin objects to include when defining your component. @@ -9226,11 +8922,13 @@ var RESERVED_SPEC_KEYS = { } }, childContextTypes: function(Constructor, childContextTypes) { - validateTypeDef( - Constructor, - childContextTypes, - ReactPropTypeLocations.childContext - ); + if ("production" !== process.env.NODE_ENV) { + validateTypeDef( + Constructor, + childContextTypes, + ReactPropTypeLocations.childContext + ); + } Constructor.childContextTypes = assign( {}, Constructor.childContextTypes, @@ -9238,11 +8936,13 @@ var RESERVED_SPEC_KEYS = { ); }, contextTypes: function(Constructor, contextTypes) { - validateTypeDef( - Constructor, - contextTypes, - ReactPropTypeLocations.context - ); + if ("production" !== process.env.NODE_ENV) { + validateTypeDef( + Constructor, + contextTypes, + ReactPropTypeLocations.context + ); + } Constructor.contextTypes = assign( {}, Constructor.contextTypes, @@ -9264,11 +8964,13 @@ var RESERVED_SPEC_KEYS = { } }, propTypes: function(Constructor, propTypes) { - validateTypeDef( - Constructor, - propTypes, - ReactPropTypeLocations.prop - ); + if ("production" !== process.env.NODE_ENV) { + validateTypeDef( + Constructor, + propTypes, + ReactPropTypeLocations.prop + ); + } Constructor.propTypes = assign( {}, Constructor.propTypes, @@ -9280,40 +8982,33 @@ var RESERVED_SPEC_KEYS = { } }; -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" !== process.env.NODE_ENV ? invariant( - typeof typeDef[propName] == 'function', + // use a warning instead of an invariant so components + // don't show up in prod but not in __DEV__ + ("production" !== process.env.NODE_ENV ? warning( + typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', - Constructor.displayName || 'ReactCompositeComponent', + Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName - ) : invariant(typeof typeDef[propName] == 'function')); + ) : null); } } } function validateMethodOverride(proto, name) { - var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ? - ReactCompositeComponentInterface[name] : + var specPolicy = ReactClassInterface.hasOwnProperty(name) ? + ReactClassInterface[name] : null; // Disallow overriding of base class methods unless explicitly allowed. - if (ReactCompositeComponentMixin.hasOwnProperty(name)) { + if (ReactClassMixin.hasOwnProperty(name)) { ("production" !== process.env.NODE_ENV ? invariant( specPolicy === SpecPolicy.OVERRIDE_BASE, - 'ReactCompositeComponentInterface: You are attempting to override ' + + 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name @@ -9325,7 +9020,7 @@ function validateMethodOverride(proto, name) { ("production" !== process.env.NODE_ENV ? invariant( specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED, - 'ReactCompositeComponentInterface: You are attempting to define ' + + 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name @@ -9334,29 +9029,9 @@ function validateMethodOverride(proto, name) { } } -function validateLifeCycleOnReplaceState(instance) { - var compositeLifeCycleState = instance._compositeLifeCycleState; - ("production" !== process.env.NODE_ENV ? invariant( - instance.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING, - 'replaceState(...): Can only update a mounted or mounting component.' - ) : invariant(instance.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); - ("production" !== process.env.NODE_ENV ? invariant( - ReactCurrentOwner.current == null, - 'replaceState(...): Cannot update during an existing state transition ' + - '(such as within `render`). Render methods should be a pure function ' + - 'of props and state.' - ) : invariant(ReactCurrentOwner.current == null)); - ("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, - 'replaceState(...): Cannot update while unmounting component. This ' + - 'usually means you called setState() on an unmounted component.' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); -} - /** * Mixin helper which handles policy validation and reserved - * specification keys when building `ReactCompositeComponent` classses. + * specification keys when building React classses. */ function mixSpecIntoComponent(Constructor, spec) { if (!spec) { @@ -9364,13 +9039,13 @@ function mixSpecIntoComponent(Constructor, spec) { } ("production" !== process.env.NODE_ENV ? invariant( - !ReactLegacyElement.isValidFactory(spec), - 'ReactCompositeComponent: You\'re attempting to ' + + typeof spec !== 'function', + 'ReactClass: You\'re attempting to ' + 'use a component class as a mixin. Instead, just use a regular object.' - ) : invariant(!ReactLegacyElement.isValidFactory(spec))); + ) : invariant(typeof spec !== 'function')); ("production" !== process.env.NODE_ENV ? invariant( !ReactElement.isValidElement(spec), - 'ReactCompositeComponent: You\'re attempting to ' + + 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.' ) : invariant(!ReactElement.isValidElement(spec))); @@ -9401,16 +9076,16 @@ function mixSpecIntoComponent(Constructor, spec) { } else { // Setup methods on prototype: // The following member methods should not be automatically bound: - // 1. Expected ReactCompositeComponent methods (in the "interface"). + // 1. Expected ReactClass methods (in the "interface"). // 2. Overridden methods (that were mixed in). - var isCompositeComponentMethod = - ReactCompositeComponentInterface.hasOwnProperty(name); + var isReactClassMethod = + ReactClassInterface.hasOwnProperty(name); var isAlreadyDefined = proto.hasOwnProperty(name); var markedDontBind = property && property.__reactDontBind; var isFunction = typeof property === 'function'; var shouldAutoBind = isFunction && - !isCompositeComponentMethod && + !isReactClassMethod && !isAlreadyDefined && !markedDontBind; @@ -9422,21 +9097,19 @@ function mixSpecIntoComponent(Constructor, spec) { proto[name] = property; } else { if (isAlreadyDefined) { - var specPolicy = ReactCompositeComponentInterface[name]; + var specPolicy = ReactClassInterface[name]; // These cases should already be caught by validateMethodOverride ("production" !== process.env.NODE_ENV ? invariant( - isCompositeComponentMethod && ( - specPolicy === SpecPolicy.DEFINE_MANY_MERGED || - specPolicy === SpecPolicy.DEFINE_MANY + isReactClassMethod && ( + (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY) ), - 'ReactCompositeComponent: Unexpected spec policy %s for key %s ' + + 'ReactClass: 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 + ) : invariant(isReactClassMethod && ( + (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY) ))); // For methods which are defined more than once, call the existing @@ -9474,7 +9147,7 @@ function mixStaticSpecIntoComponent(Constructor, statics) { var isReserved = name in RESERVED_SPEC_KEYS; ("production" !== process.env.NODE_ENV ? invariant( !isReserved, - 'ReactCompositeComponent: You are attempting to define a reserved ' + + 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', @@ -9484,7 +9157,7 @@ function mixStaticSpecIntoComponent(Constructor, statics) { var isInherited = name in Constructor; ("production" !== process.env.NODE_ENV ? invariant( !isInherited, - 'ReactCompositeComponent: You are attempting to define ' + + 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name @@ -9500,24 +9173,26 @@ function mixStaticSpecIntoComponent(Constructor, statics) { * @param {object} two The second object * @return {object} one after it has been mutated to contain everything in two. */ -function mergeObjectsWithNoDuplicateKeys(one, two) { +function mergeIntoWithNoDuplicateKeys(one, two) { ("production" !== process.env.NODE_ENV ? invariant( one && two && typeof one === 'object' && typeof two === 'object', - 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects' + 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.' ) : invariant(one && two && typeof one === 'object' && typeof two === 'object')); - mapObject(two, function(value, key) { - ("production" !== process.env.NODE_ENV ? invariant( - one[key] === undefined, - 'mergeObjectsWithNoDuplicateKeys(): ' + - 'Tried to merge two objects with the same key: `%s`. This conflict ' + - 'may be due to a mixin; in particular, this may be caused by two ' + - 'getInitialState() or getDefaultProps() methods returning objects ' + - 'with clashing keys.', - key - ) : invariant(one[key] === undefined)); - one[key] = value; - }); + for (var key in two) { + if (two.hasOwnProperty(key)) { + ("production" !== process.env.NODE_ENV ? invariant( + one[key] === undefined, + 'mergeIntoWithNoDuplicateKeys(): ' + + 'Tried to merge two objects with the same key: `%s`. This conflict ' + + 'may be due to a mixin; in particular, this may be caused by two ' + + 'getInitialState() or getDefaultProps() methods returning objects ' + + 'with clashing keys.', + key + ) : invariant(one[key] === undefined)); + one[key] = two[key]; + } + } return one; } @@ -9538,7 +9213,10 @@ function createMergedResultFunction(one, two) { } else if (b == null) { return a; } - return mergeObjectsWithNoDuplicateKeys(a, b); + var c = {}; + mergeIntoWithNoDuplicateKeys(c, a); + mergeIntoWithNoDuplicateKeys(c, b); + return c; }; } @@ -9558,48 +9236,680 @@ function createChainedFunction(one, two) { } /** - * `ReactCompositeComponent` maintains an auxiliary life cycle state in - * `this._compositeLifeCycleState` (which can be null). + * Binds a method to the component. + * + * @param {object} component Component whose method is going to be bound. + * @param {function} method Method to be bound. + * @return {function} The bound method. + */ +function bindAutoBindMethod(component, method) { + var boundMethod = method.bind(component); + if ("production" !== process.env.NODE_ENV) { + boundMethod.__reactBoundContext = component; + boundMethod.__reactBoundMethod = method; + boundMethod.__reactBoundArguments = null; + var componentName = component.constructor.displayName; + var _bind = boundMethod.bind; + /* eslint-disable block-scoped-var, no-undef */ + boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); + // User is trying to bind() an autobound method; we effectively will + // ignore the value of "this" that the user is trying to use, so + // let's warn. + if (newThis !== component && newThis !== null) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'bind(): React component methods may only be bound to the ' + + 'component instance. See %s', + componentName + ) : null); + } else if (!args.length) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'bind(): You are binding a component method to the component. ' + + 'React does this for you automatically in a high-performance ' + + 'way, so you can safely remove this call. See %s', + componentName + ) : null); + return boundMethod; + } + var reboundMethod = _bind.apply(boundMethod, arguments); + reboundMethod.__reactBoundContext = component; + reboundMethod.__reactBoundMethod = method; + reboundMethod.__reactBoundArguments = args; + return reboundMethod; + /* eslint-enable */ + }; + } + return boundMethod; +} + +/** + * Binds all auto-bound methods in a component. + * + * @param {object} component Component whose method is going to be bound. + */ +function bindAutoBindMethods(component) { + for (var autoBindKey in component.__reactAutoBindMap) { + if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { + var method = component.__reactAutoBindMap[autoBindKey]; + component[autoBindKey] = bindAutoBindMethod( + component, + ReactErrorUtils.guard( + method, + component.constructor.displayName + '.' + autoBindKey + ) + ); + } + } +} + +var typeDeprecationDescriptor = { + enumerable: false, + get: function() { + var displayName = this.displayName || this.name || 'Component'; + ("production" !== process.env.NODE_ENV ? warning( + false, + '%s.type is deprecated. Use %s directly to access the class.', + displayName, + displayName + ) : null); + Object.defineProperty(this, 'type', { + value: this + }); + return this; + } +}; + +/** + * Add more to the ReactClass base class. These are all legacy features and + * therefore not already part of the modern ReactComponent. + */ +var ReactClassMixin = { + + /** + * TODO: This will be deprecated because state should always keep a consistent + * type signature and the only use case for this, is to avoid that. + */ + replaceState: function(newState, callback) { + ReactUpdateQueue.enqueueReplaceState(this, newState); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + }, + + /** + * Checks whether or not this composite component is mounted. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function() { + if ("production" !== process.env.NODE_ENV) { + var owner = ReactCurrentOwner.current; + if (owner !== null) { + ("production" !== process.env.NODE_ENV ? warning( + owner._warnedAboutRefsInRender, + '%s is accessing isMounted inside its render() function. ' + + 'render() should be a pure function of props and state. It should ' + + 'never access something that requires stale data from the previous ' + + 'render, such as refs. Move this logic to componentDidMount and ' + + 'componentDidUpdate instead.', + owner.getName() || 'A component' + ) : null); + owner._warnedAboutRefsInRender = true; + } + } + var internalInstance = ReactInstanceMap.get(this); + return ( + internalInstance && + internalInstance !== ReactLifeCycle.currentlyMountingInstance + ); + }, + + /** + * Sets a subset of the props. + * + * @param {object} partialProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated + */ + setProps: function(partialProps, callback) { + ReactUpdateQueue.enqueueSetProps(this, partialProps); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + }, + + /** + * Replace all the props. + * + * @param {object} newProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated + */ + replaceProps: function(newProps, callback) { + ReactUpdateQueue.enqueueReplaceProps(this, newProps); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + } +}; + +var ReactClassComponent = function() {}; +assign( + ReactClassComponent.prototype, + ReactComponent.prototype, + ReactClassMixin +); + +/** + * Module for creating composite components. + * + * @class ReactClass + */ +var ReactClass = { + + /** + * 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(props, context) { + // This constructor is overridden by mocks. The argument is used + // by mocks to assert on what gets mounted. + + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + this instanceof Constructor, + 'Something is calling a React component directly. Use a factory or ' + + 'JSX instead. See: http://fb.me/react-legacyfactory' + ) : null); + } + + // Wire up auto-binding + if (this.__reactAutoBindMap) { + bindAutoBindMethods(this); + } + + this.props = props; + this.context = context; + this.state = null; + + // ReactClasses doesn't have constructors. Instead, they use the + // getInitialState and componentWillMount methods for initialization. + + var initialState = this.getInitialState ? this.getInitialState() : null; + if ("production" !== process.env.NODE_ENV) { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof initialState === 'undefined' && + this.getInitialState._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + initialState = null; + } + } + ("production" !== process.env.NODE_ENV ? invariant( + typeof initialState === 'object' && !Array.isArray(initialState), + '%s.getInitialState(): must return an object or null', + Constructor.displayName || 'ReactCompositeComponent' + ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState))); + + this.state = initialState; + }; + Constructor.prototype = new ReactClassComponent(); + Constructor.prototype.constructor = Constructor; + + injectedMixins.forEach( + mixSpecIntoComponent.bind(null, Constructor) + ); + + mixSpecIntoComponent(Constructor, spec); + + // Initialize the defaultProps property after all mixins have been merged + if (Constructor.getDefaultProps) { + Constructor.defaultProps = Constructor.getDefaultProps(); + } + + if ("production" !== process.env.NODE_ENV) { + // This is a tag to indicate that the use of these method names is ok, + // since it's used with createClass. If it's not, then it's likely a + // mistake so we'll warn you to use the static property, property + // initializer or constructor respectively. + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps.isReactClassApproved = {}; + } + if (Constructor.prototype.getInitialState) { + Constructor.prototype.getInitialState.isReactClassApproved = {}; + } + } + + ("production" !== process.env.NODE_ENV ? invariant( + Constructor.prototype.render, + 'createClass(...): Class specification must implement a `render` method.' + ) : invariant(Constructor.prototype.render)); + + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + !Constructor.prototype.componentShouldUpdate, + '%s 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.', + spec.displayName || 'A component' + ) : null); + } + + // Reduce time spent doing lookups by setting these on the prototype. + for (var methodName in ReactClassInterface) { + if (!Constructor.prototype[methodName]) { + Constructor.prototype[methodName] = null; + } + } + + // Legacy hook + Constructor.type = Constructor; + if ("production" !== process.env.NODE_ENV) { + try { + Object.defineProperty(Constructor, 'type', typeDeprecationDescriptor); + } catch (x) { + // IE will fail on defineProperty (es5-shim/sham too) + } + } + + return Constructor; + }, + + injection: { + injectMixin: function(mixin) { + injectedMixins.push(mixin); + } + } + +}; + +module.exports = ReactClass; + +}).call(this,require('_process')) +},{"./Object.assign":67,"./ReactComponent":77,"./ReactCurrentOwner":83,"./ReactElement":101,"./ReactErrorUtils":104,"./ReactInstanceMap":111,"./ReactLifeCycle":112,"./ReactPropTypeLocationNames":122,"./ReactPropTypeLocations":123,"./ReactUpdateQueue":137,"./invariant":189,"./keyMirror":195,"./keyOf":196,"./warning":210,"_process":1}],77:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponent + */ + +'use strict'; + +var ReactUpdateQueue = require("./ReactUpdateQueue"); + +var invariant = require("./invariant"); +var warning = require("./warning"); + +/** + * Base class helpers for the updating state of a component. + */ +function ReactComponent(props, context) { + this.props = props; + this.context = context; +} + +/** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ +ReactComponent.prototype.setState = function(partialState, callback) { + ("production" !== process.env.NODE_ENV ? invariant( + typeof partialState === 'object' || + typeof partialState === 'function' || + partialState == null, + 'setState(...): takes an object of state variables to update or a ' + + 'function which returns an object of state variables.' + ) : invariant(typeof partialState === 'object' || + typeof partialState === 'function' || + partialState == null)); + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + partialState != null, + 'setState(...): You passed an undefined or null state object; ' + + 'instead, use forceUpdate().' + ) : null); + } + ReactUpdateQueue.enqueueSetState(this, partialState); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } +}; + +/** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ +ReactComponent.prototype.forceUpdate = function(callback) { + ReactUpdateQueue.enqueueForceUpdate(this); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } +}; + +/** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ +if ("production" !== process.env.NODE_ENV) { + var deprecatedAPIs = { + getDOMNode: 'getDOMNode', + isMounted: 'isMounted', + replaceProps: 'replaceProps', + replaceState: 'replaceState', + setProps: 'setProps' + }; + var defineDeprecationWarning = function(methodName, displayName) { + try { + Object.defineProperty(ReactComponent.prototype, methodName, { + get: function() { + ("production" !== process.env.NODE_ENV ? warning( + false, + '%s(...) is deprecated in plain JavaScript React classes.', + displayName + ) : null); + return undefined; + } + }); + } catch (x) { + // IE will fail on defineProperty (es5-shim/sham too) + } + }; + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } +} + +module.exports = ReactComponent; + +}).call(this,require('_process')) +},{"./ReactUpdateQueue":137,"./invariant":189,"./warning":210,"_process":1}],78:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentBrowserEnvironment + */ + +/*jslint evil: true */ + +'use strict'; + +var ReactDOMIDOperations = require("./ReactDOMIDOperations"); +var ReactMount = require("./ReactMount"); + +/** + * Abstracts away all functionality of the reconciler that requires knowledge of + * the browser context. TODO: These callers should be refactored to avoid the + * need for this injection. + */ +var ReactComponentBrowserEnvironment = { + + processChildrenUpdates: + ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, + + replaceNodeWithMarkupByID: + ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID, + + /** + * If a particular environment requires that some resources be cleaned up, + * specify this in the injected Mixin. In the DOM, we would likely want to + * purge any cached node ID lookups. + * + * @private + */ + unmountIDFromEnvironment: function(rootNodeID) { + ReactMount.purgeID(rootNodeID); + } + +}; + +module.exports = ReactComponentBrowserEnvironment; + +},{"./ReactDOMIDOperations":88,"./ReactMount":115}],79:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2014-2015, Facebook, Inc. + * All rights reserved. * - * Top Row: ReactComponent.ComponentLifeCycle - * Low Row: ReactComponent.CompositeLifeCycle + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * +-------+---------------------------------+--------+ - * | UN | MOUNTED | UN | - * |MOUNTED| | MOUNTED| - * +-------+---------------------------------+--------+ - * | ^--------+ +-------+ +--------^ | - * | | | | | | | | - * | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 | - * | | | |PROPS | |MOUNTING| | - * | | | | | | | | - * | | | | | | | | - * | +--------+ +-------+ +--------+ | - * | | | | - * +-------+---------------------------------+--------+ + * @providesModule ReactComponentEnvironment */ -var CompositeLifeCycle = keyMirror({ + +'use strict'; + +var invariant = require("./invariant"); + +var injected = false; + +var ReactComponentEnvironment = { + /** - * Components in the process of being mounted respond to state changes - * differently. + * 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. */ - MOUNTING: null, + unmountIDFromEnvironment: null, + /** - * Components in the process of being unmounted are guarded against state - * changes. + * Optionally injectable hook for swapping out mount images in the middle of + * the tree. */ - UNMOUNTING: null, + replaceNodeWithMarkupByID: null, + /** - * Components that are mounted and receiving new props respond to state - * changes differently. + * Optionally injectable hook for processing a queue of child updates. Will + * later move into MultiChildComponents. */ - RECEIVING_PROPS: null -}); + processChildrenUpdates: null, + + injection: { + injectEnvironment: function(environment) { + ("production" !== process.env.NODE_ENV ? invariant( + !injected, + 'ReactCompositeComponent: injectEnvironment() can only be called once.' + ) : invariant(!injected)); + ReactComponentEnvironment.unmountIDFromEnvironment = + environment.unmountIDFromEnvironment; + ReactComponentEnvironment.replaceNodeWithMarkupByID = + environment.replaceNodeWithMarkupByID; + ReactComponentEnvironment.processChildrenUpdates = + environment.processChildrenUpdates; + injected = true; + } + } + +}; + +module.exports = ReactComponentEnvironment; + +}).call(this,require('_process')) +},{"./invariant":189,"_process":1}],80:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * +* @providesModule ReactComponentWithPureRenderMixin +*/ + +'use strict'; + +var shallowEqual = require("./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":205}],81:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactCompositeComponent + */ + +'use strict'; + +var ReactComponentEnvironment = require("./ReactComponentEnvironment"); +var ReactContext = require("./ReactContext"); +var ReactCurrentOwner = require("./ReactCurrentOwner"); +var ReactElement = require("./ReactElement"); +var ReactElementValidator = require("./ReactElementValidator"); +var ReactInstanceMap = require("./ReactInstanceMap"); +var ReactLifeCycle = require("./ReactLifeCycle"); +var ReactNativeComponent = require("./ReactNativeComponent"); +var ReactPerf = require("./ReactPerf"); +var ReactPropTypeLocations = require("./ReactPropTypeLocations"); +var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames"); +var ReactReconciler = require("./ReactReconciler"); +var ReactUpdates = require("./ReactUpdates"); + +var assign = require("./Object.assign"); +var emptyObject = require("./emptyObject"); +var invariant = require("./invariant"); +var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); +var warning = require("./warning"); + +function getDeclarationErrorAddendum(component) { + var owner = component._currentElement._owner || null; + if (owner) { + var name = owner.getName(); + if (name) { + return ' Check the render method of `' + name + '`.'; + } + } + return ''; +} + +/** + * ------------------ The Life-Cycle of a Composite Component ------------------ + * + * - constructor: Initialization of state. The instance is now retained. + * - componentWillMount + * - render + * - [children's constructors] + * - [children's componentWillMount and render] + * - [children's componentDidMount] + * - componentDidMount + * + * Update Phases: + * - componentWillReceiveProps (only called if parent updated) + * - shouldComponentUpdate + * - componentWillUpdate + * - render + * - [children's constructors or receive props phases] + * - componentDidUpdate + * + * - componentWillUnmount + * - [children's componentWillUnmount] + * - [children destroyed] + * - (destroyed): The instance is now blank, released by React and ready for GC. + * + * ----------------------------------------------------------------------------- + */ + +/** + * An incrementing ID assigned to each component when it is mounted. This is + * used to enforce the order in which `ReactUpdates` updates dirty components. + * + * @private + */ +var nextMountID = 1; /** * @lends {ReactCompositeComponent.prototype} @@ -9614,29 +9924,24 @@ var ReactCompositeComponentMixin = { * @internal */ construct: function(element) { - // Children can be either an array or more than one argument - ReactComponent.Mixin.construct.apply(this, arguments); - ReactOwner.Mixin.construct.apply(this, arguments); + this._currentElement = element; + this._rootNodeID = null; + this._instance = null; - this.state = null; - this._pendingState = null; + // See ReactUpdateQueue + this._pendingElement = null; + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; - // This is the public post-processed context. The real context and pending - // context lives on the element. - this.context = null; + this._renderedComponent = null; - this._compositeLifeCycleState = null; - }, + this._context = null; + this._mountOrder = 0; + this._isTopLevel = false; - /** - * 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; + // See ReactUpdates and ReactUpdateQueue. + this._pendingCallbacks = null; }, /** @@ -9644,68 +9949,137 @@ var ReactCompositeComponentMixin = { * * @param {string} rootID DOM ID of the root node. * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy * @return {?string} Rendered markup to be inserted into the DOM. * @final * @internal */ - mountComponent: ReactPerf.measure( - 'ReactCompositeComponent', - 'mountComponent', - function(rootID, transaction, mountDepth) { - ReactComponent.Mixin.mountComponent.call( - this, - rootID, - transaction, - mountDepth - ); - this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; + mountComponent: function(rootID, transaction, context) { + this._context = context; + this._mountOrder = nextMountID++; + this._rootNodeID = rootID; - if (this.__reactAutoBindMap) { - this._bindAutoBindMethods(); - } + var publicProps = this._processProps(this._currentElement.props); + var publicContext = this._processContext(this._currentElement._context); + + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); - this.context = this._processContext(this._currentElement._context); - this.props = this._processProps(this.props); + // Initialize the public class + var inst = new Component(publicProps, publicContext); - this.state = this.getInitialState ? this.getInitialState() : null; - ("production" !== process.env.NODE_ENV ? 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))); + if ("production" !== process.env.NODE_ENV) { + // This will throw later in _renderValidatedComponent, but add an early + // warning now to help debugging + ("production" !== process.env.NODE_ENV ? warning( + inst.render != null, + '%s(...): No `render` method found on the returned component ' + + 'instance: you may have forgotten to define `render` in your ' + + 'component or you may have accidentally tried to render an element ' + + 'whose type is a function that isn\'t a React component.', + Component.displayName || Component.name || 'Component' + ) : null); + } - this._pendingState = null; - this._pendingForceUpdate = false; + // These should be set up in the constructor, but as a convenience for + // simpler class abstractions, we set them up after the fact. + inst.props = publicProps; + inst.context = publicContext; + inst.refs = emptyObject; + + this._instance = inst; + + // Store a reference from the instance back to the internal representation + ReactInstanceMap.set(inst, this); + + if ("production" !== process.env.NODE_ENV) { + this._warnIfContextsDiffer(this._currentElement._context, context); + } + + if ("production" !== process.env.NODE_ENV) { + // Since plain JS classes are defined without any special initialization + // logic, we can not catch common errors early. Therefore, we have to + // catch them here, at initialization time, instead. + ("production" !== process.env.NODE_ENV ? warning( + !inst.getInitialState || + inst.getInitialState.isReactClassApproved, + 'getInitialState was defined on %s, a plain JavaScript class. ' + + 'This is only supported for classes created using React.createClass. ' + + 'Did you mean to define a state property instead?', + this.getName() || 'a component' + ) : null); + ("production" !== process.env.NODE_ENV ? warning( + !inst.propTypes, + 'propTypes was defined as an instance property on %s. Use a static ' + + 'property to define propTypes instead.', + this.getName() || 'a component' + ) : null); + ("production" !== process.env.NODE_ENV ? warning( + !inst.contextTypes, + 'contextTypes was defined as an instance property on %s. Use a ' + + 'static property to define contextTypes instead.', + this.getName() || 'a component' + ) : null); + ("production" !== process.env.NODE_ENV ? warning( + typeof inst.componentShouldUpdate !== 'function', + '%s 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.', + (this.getName() || 'A component') + ) : null); + } + + var initialState = inst.state; + if (initialState === undefined) { + inst.state = initialState = null; + } + ("production" !== process.env.NODE_ENV ? invariant( + typeof initialState === 'object' && !Array.isArray(initialState), + '%s.state: must be set to an object or null', + this.getName() || 'ReactCompositeComponent' + ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState))); + + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + var renderedElement; - if (this.componentWillMount) { - this.componentWillMount(); + var previouslyMounting = ReactLifeCycle.currentlyMountingInstance; + ReactLifeCycle.currentlyMountingInstance = this; + try { + if (inst.componentWillMount) { + inst.componentWillMount(); // When mounting, calls to `setState` by `componentWillMount` will set - // `this._pendingState` without triggering a re-render. - if (this._pendingState) { - this.state = this._pendingState; - this._pendingState = null; + // `this._pendingStateQueue` without triggering a re-render. + if (this._pendingStateQueue) { + inst.state = this._processPendingState(inst.props, inst.context); } } - this._renderedComponent = instantiateReactComponent( - this._renderValidatedComponent(), - this._currentElement.type // The wrapping type - ); + renderedElement = this._renderValidatedComponent(); + } finally { + ReactLifeCycle.currentlyMountingInstance = previouslyMounting; + } - // 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.componentDidMount, this); - } - return markup; + this._renderedComponent = this._instantiateReactComponent( + renderedElement, + this._currentElement.type // The wrapping type + ); + + var markup = ReactReconciler.mountComponent( + this._renderedComponent, + rootID, + transaction, + this._processChildContext(context) + ); + if (inst.componentDidMount) { + transaction.getReactMountReady().enqueue(inst.componentDidMount, inst); } - ), + + return markup; + }, /** * Releases any resources allocated by `mountComponent`. @@ -9714,83 +10088,88 @@ var ReactCompositeComponentMixin = { * @internal */ unmountComponent: function() { - this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING; - if (this.componentWillUnmount) { - this.componentWillUnmount(); + var inst = this._instance; + + if (inst.componentWillUnmount) { + var previouslyUnmounting = ReactLifeCycle.currentlyUnmountingInstance; + ReactLifeCycle.currentlyUnmountingInstance = this; + try { + inst.componentWillUnmount(); + } finally { + ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting; + } } - this._compositeLifeCycleState = null; - this._renderedComponent.unmountComponent(); + ReactReconciler.unmountComponent(this._renderedComponent); this._renderedComponent = null; - ReactComponent.Mixin.unmountComponent.call(this); + // Reset pending fields + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + this._pendingCallbacks = null; + this._pendingElement = null; - // Some existing components rely on this.props even after they've been + // These fields do not really need to be reset since this object is no + // longer accessible. + this._context = null; + this._rootNodeID = null; + + // Delete the reference from the instance to this internal representation + // which allow the internals to be properly cleaned up even if the user + // leaks a reference to the public instance. + ReactInstanceMap.remove(inst); + + // Some existing components rely on inst.props even after they've been // destroyed (in event handlers). - // TODO: this.props = null; - // TODO: this.state = null; + // TODO: inst.props = null; + // TODO: inst.state = null; + // TODO: inst.context = null; }, /** - * Sets a subset of the state. Always use this or `replaceState` to mutate - * state. You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. + * Schedule a partial update to the props. Only used for internal testing. * - * There is no guarantee that calls to `setState` will run synchronously, - * as they may eventually be batched together. You can provide an optional - * callback that will be executed when the call to setState is actually - * completed. - * - * @param {object} partialState Next partial state to be merged with state. - * @param {?function} callback Called after state is updated. + * @param {object} partialProps Subset of the next props. + * @param {?function} callback Called after props are updated. * @final - * @protected + * @internal */ - setState: function(partialState, callback) { - ("production" !== process.env.NODE_ENV ? invariant( - typeof partialState === 'object' || partialState == null, - 'setState(...): takes an object of state variables to update.' - ) : invariant(typeof partialState === 'object' || partialState == null)); - if ("production" !== process.env.NODE_ENV){ - ("production" !== process.env.NODE_ENV ? 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( - assign({}, this._pendingState || this.state, partialState), - callback + _setPropsInternal: function(partialProps, callback) { + // This is a deoptimized path. We optimize for always having an element. + // This creates an extra internal element. + var element = this._pendingElement || this._currentElement; + this._pendingElement = ReactElement.cloneAndReplaceProps( + element, + assign({}, element.props, partialProps) ); + ReactUpdates.enqueueUpdate(this, callback); }, /** - * Replaces all of the state. Always use this or `setState` to mutate state. - * You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. + * Filters the context object to only contain keys specified in + * `contextTypes` * - * @param {object} completeState Next state. - * @param {?function} callback Called after state is updated. - * @final - * @protected + * @param {object} context + * @return {?object} + * @private */ - replaceState: function(completeState, callback) { - validateLifeCycleOnReplaceState(this); - this._pendingState = completeState; - 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); + _maskContext: function(context) { + var maskedContext = null; + // This really should be getting the component class for the element, + // but we know that we're not going to need it for built-ins. + if (typeof this._currentElement.type === 'string') { + return emptyObject; } + var contextTypes = this._currentElement.type.contextTypes; + if (!contextTypes) { + return emptyObject; + } + maskedContext = {}; + for (var contextName in contextTypes) { + maskedContext[contextName] = context[contextName]; + } + return maskedContext; }, /** @@ -9802,16 +10181,14 @@ var ReactCompositeComponentMixin = { * @private */ _processContext: function(context) { - var maskedContext = null; - var contextTypes = this.constructor.contextTypes; - if (contextTypes) { - maskedContext = {}; - for (var contextName in contextTypes) { - maskedContext[contextName] = context[contextName]; - } - if ("production" !== process.env.NODE_ENV) { + var maskedContext = this._maskContext(context); + if ("production" !== process.env.NODE_ENV) { + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); + if (Component.contextTypes) { this._checkPropTypes( - contextTypes, + Component.contextTypes, maskedContext, ReactPropTypeLocations.context ); @@ -9826,29 +10203,29 @@ var ReactCompositeComponentMixin = { * @private */ _processChildContext: function(currentContext) { - var childContext = this.getChildContext && this.getChildContext(); - var displayName = this.constructor.displayName || 'ReactCompositeComponent'; + var inst = this._instance; + var childContext = inst.getChildContext && inst.getChildContext(); if (childContext) { ("production" !== process.env.NODE_ENV ? invariant( - typeof this.constructor.childContextTypes === 'object', + typeof inst.constructor.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', - displayName - ) : invariant(typeof this.constructor.childContextTypes === 'object')); + this.getName() || 'ReactCompositeComponent' + ) : invariant(typeof inst.constructor.childContextTypes === 'object')); if ("production" !== process.env.NODE_ENV) { this._checkPropTypes( - this.constructor.childContextTypes, + inst.constructor.childContextTypes, childContext, ReactPropTypeLocations.childContext ); } for (var name in childContext) { ("production" !== process.env.NODE_ENV ? invariant( - name in this.constructor.childContextTypes, + name in inst.constructor.childContextTypes, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - displayName, + this.getName() || 'ReactCompositeComponent', name - ) : invariant(name in this.constructor.childContextTypes)); + ) : invariant(name in inst.constructor.childContextTypes)); } return assign({}, currentContext, childContext); } @@ -9866,9 +10243,15 @@ var ReactCompositeComponentMixin = { */ _processProps: function(newProps) { if ("production" !== process.env.NODE_ENV) { - var propTypes = this.constructor.propTypes; - if (propTypes) { - this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop); + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); + if (Component.propTypes) { + this._checkPropTypes( + Component.propTypes, + newProps, + ReactPropTypeLocations.prop + ); } } return newProps; @@ -9885,101 +10268,236 @@ var ReactCompositeComponentMixin = { _checkPropTypes: function(propTypes, props, location) { // TODO: Stop validating prop types here and only use the element // validation. - var componentName = this.constructor.displayName; + var componentName = this.getName(); for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { - var error = - propTypes[propName](props, propName, componentName, location); + var error; + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + ("production" !== process.env.NODE_ENV ? invariant( + typeof propTypes[propName] === 'function', + '%s: %s type `%s` is invalid; it must be a function, usually ' + + 'from React.PropTypes.', + componentName || 'React class', + ReactPropTypeLocationNames[location], + propName + ) : invariant(typeof propTypes[propName] === 'function')); + error = propTypes[propName](props, propName, componentName, location); + } catch (ex) { + error = ex; + } if (error instanceof Error) { // We may want to extend this logic for similar errors in - // renderComponent calls, so I'm abstracting it away into + // React.render calls, so I'm abstracting it away into // a function to minimize refactoring in the future var addendum = getDeclarationErrorAddendum(this); - ("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null); + + if (location === ReactPropTypeLocations.prop) { + // Preface gives us something to blacklist in warning module + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Failed Composite propType: %s%s', + error.message, + addendum + ) : null); + } else { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Failed Context Types: %s%s', + error.message, + addendum + ) : null); + } } } } }, + receiveComponent: function(nextElement, transaction, nextContext) { + var prevElement = this._currentElement; + var prevContext = this._context; + + this._pendingElement = null; + + this.updateComponent( + transaction, + prevElement, + nextElement, + prevContext, + nextContext + ); + }, + /** - * If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate` + * If any of `_pendingElement`, `_pendingStateQueue`, 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; + if (this._pendingElement != null) { + ReactReconciler.receiveComponent( + this, + this._pendingElement || this._currentElement, + transaction, + this._context + ); } - if (this._pendingElement == null && - this._pendingState == null && - !this._pendingForceUpdate) { - return; + if (this._pendingStateQueue !== null || this._pendingForceUpdate) { + if ("production" !== process.env.NODE_ENV) { + ReactElementValidator.checkAndWarnForMutatedProps( + this._currentElement + ); + } + + this.updateComponent( + transaction, + this._currentElement, + this._currentElement, + this._context, + this._context + ); } + }, - var nextContext = this.context; - var nextProps = this.props; - var nextElement = this._currentElement; - if (this._pendingElement != null) { - nextElement = this._pendingElement; - nextContext = this._processContext(nextElement._context); - nextProps = this._processProps(nextElement.props); - this._pendingElement = null; + /** + * Compare two contexts, warning if they are different + * TODO: Remove this check when owner-context is removed + */ + _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) { + ownerBasedContext = this._maskContext(ownerBasedContext); + parentBasedContext = this._maskContext(parentBasedContext); + var parentKeys = Object.keys(parentBasedContext).sort(); + var displayName = this.getName() || 'ReactCompositeComponent'; + for (var i = 0; i < parentKeys.length; i++) { + var key = parentKeys[i]; + ("production" !== process.env.NODE_ENV ? warning( + ownerBasedContext[key] === parentBasedContext[key], + 'owner-based and parent-based contexts differ ' + + '(values: `%s` vs `%s`) for key (%s) while mounting %s ' + + '(see: http://fb.me/react-context-by-parent)', + ownerBasedContext[key], + parentBasedContext[key], + key, + displayName + ) : null); + } + }, - this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS; - if (this.componentWillReceiveProps) { - this.componentWillReceiveProps(nextProps, nextContext); + /** + * Perform an update to a mounted component. The componentWillReceiveProps and + * shouldComponentUpdate methods are called, then (assuming the update isn't + * skipped) the remaining update lifecycle methods are called and the DOM + * representation is updated. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @param {ReactElement} prevParentElement + * @param {ReactElement} nextParentElement + * @internal + * @overridable + */ + updateComponent: function( + transaction, + prevParentElement, + nextParentElement, + prevUnmaskedContext, + nextUnmaskedContext + ) { + var inst = this._instance; + + var nextContext = inst.context; + var nextProps = inst.props; + + // Distinguish between a props update versus a simple state update + if (prevParentElement !== nextParentElement) { + nextContext = this._processContext(nextParentElement._context); + nextProps = this._processProps(nextParentElement.props); + + if ("production" !== process.env.NODE_ENV) { + if (nextUnmaskedContext != null) { + this._warnIfContextsDiffer( + nextParentElement._context, + nextUnmaskedContext + ); + } } - } - this._compositeLifeCycleState = null; + // An update here will schedule an update but immediately set + // _pendingStateQueue which will ensure that any state updates gets + // immediately reconciled instead of waiting for the next batch. + + if (inst.componentWillReceiveProps) { + inst.componentWillReceiveProps(nextProps, nextContext); + } + } - var nextState = this._pendingState || this.state; - this._pendingState = null; + var nextState = this._processPendingState(nextProps, nextContext); var shouldUpdate = this._pendingForceUpdate || - !this.shouldComponentUpdate || - this.shouldComponentUpdate(nextProps, nextState, nextContext); + !inst.shouldComponentUpdate || + inst.shouldComponentUpdate(nextProps, nextState, nextContext); if ("production" !== process.env.NODE_ENV) { - 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.' - ); - } + ("production" !== process.env.NODE_ENV ? warning( + typeof shouldUpdate !== 'undefined', + '%s.shouldComponentUpdate(): Returned undefined instead of a ' + + 'boolean value. Make sure to return true or false.', + this.getName() || 'ReactCompositeComponent' + ) : null); } if (shouldUpdate) { this._pendingForceUpdate = false; // Will set `this.props`, `this.state` and `this.context`. this._performComponentUpdate( - nextElement, + nextParentElement, nextProps, nextState, nextContext, - transaction + transaction, + nextUnmaskedContext ); } else { // If it's determined that a component should not update, we still want - // to set props and state. - this._currentElement = nextElement; - this.props = nextProps; - this.state = nextState; - this.context = nextContext; + // to set props and state but we shortcut the rest of the update. + this._currentElement = nextParentElement; + this._context = nextUnmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + } + }, + + _processPendingState: function(props, context) { + var inst = this._instance; + var queue = this._pendingStateQueue; + var replace = this._pendingReplaceState; + this._pendingReplaceState = false; + this._pendingStateQueue = null; + + if (!queue) { + return inst.state; + } - // Owner cannot change because shouldUpdateReactComponent doesn't allow - // it. TODO: Remove this._owner completely. - this._owner = nextElement._owner; + var nextState = assign({}, replace ? queue[0] : inst.state); + for (var i = replace ? 1 : 0; i < queue.length; i++) { + var partial = queue[i]; + assign( + nextState, + typeof partial === 'function' ? + partial.call(inst, nextState, props, context) : + partial + ); } + + return nextState; }, /** @@ -9991,6 +10509,7 @@ var ReactCompositeComponentMixin = { * @param {?object} nextState Next object to set as state. * @param {?object} nextContext Next public object to set as context. * @param {ReactReconcileTransaction} transaction + * @param {?object} unmaskedContext * @private */ _performComponentUpdate: function( @@ -9998,337 +10517,213 @@ var ReactCompositeComponentMixin = { nextProps, nextState, nextContext, - transaction + transaction, + unmaskedContext ) { - var prevElement = this._currentElement; - var prevProps = this.props; - var prevState = this.state; - var prevContext = this.context; + var inst = this._instance; + + var prevProps = inst.props; + var prevState = inst.state; + var prevContext = inst.context; - if (this.componentWillUpdate) { - this.componentWillUpdate(nextProps, nextState, nextContext); + if (inst.componentWillUpdate) { + inst.componentWillUpdate(nextProps, nextState, nextContext); } this._currentElement = nextElement; - this.props = nextProps; - this.state = nextState; - this.context = nextContext; + this._context = unmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; - // Owner cannot change because shouldUpdateReactComponent doesn't allow - // it. TODO: Remove this._owner completely. - this._owner = nextElement._owner; + this._updateRenderedComponent(transaction, unmaskedContext); - this.updateComponent( - transaction, - prevElement - ); - - if (this.componentDidUpdate) { + if (inst.componentDidUpdate) { transaction.getReactMountReady().enqueue( - this.componentDidUpdate.bind(this, prevProps, prevState, prevContext), - this + inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), + inst ); } }, - receiveComponent: function(nextElement, transaction) { - if (nextElement === this._currentElement && - nextElement._owner != null) { - // Since elements 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 element. We explicitly check for the existence of an owner since - // it's possible for a element created outside a composite to be - // deeply mutated and reused. - return; - } - - ReactComponent.Mixin.receiveComponent.call( - this, - nextElement, - 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. + * Call the component's `render` method and update the DOM accordingly. * * @param {ReactReconcileTransaction} transaction - * @param {ReactElement} prevElement * @internal - * @overridable */ - updateComponent: ReactPerf.measure( - 'ReactCompositeComponent', - 'updateComponent', - function(transaction, prevParentElement) { - ReactComponent.Mixin.updateComponent.call( - this, + _updateRenderedComponent: function(transaction, context) { + var prevComponentInstance = this._renderedComponent; + var prevRenderedElement = prevComponentInstance._currentElement; + var nextRenderedElement = this._renderValidatedComponent(); + if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) { + ReactReconciler.receiveComponent( + prevComponentInstance, + nextRenderedElement, transaction, - prevParentElement + this._processChildContext(context) ); - - var prevComponentInstance = this._renderedComponent; - var prevElement = prevComponentInstance._currentElement; - var nextElement = this._renderValidatedComponent(); - if (shouldUpdateReactComponent(prevElement, nextElement)) { - prevComponentInstance.receiveComponent(nextElement, 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( - nextElement, - this._currentElement.type - ); - var nextMarkup = this._renderedComponent.mountComponent( - thisID, - transaction, - this._mountDepth + 1 - ); - ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID( - prevComponentID, - nextMarkup - ); - } + } else { + // These two IDs are actually the same! But nothing should rely on that. + var thisID = this._rootNodeID; + var prevComponentID = prevComponentInstance._rootNodeID; + ReactReconciler.unmountComponent(prevComponentInstance); + + this._renderedComponent = this._instantiateReactComponent( + nextRenderedElement, + this._currentElement.type + ); + var nextMarkup = ReactReconciler.mountComponent( + this._renderedComponent, + thisID, + transaction, + context + ); + this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup); } - ), + }, /** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldUpdateComponent`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {?function} callback Called after update is complete. - * @final * @protected */ - forceUpdate: function(callback) { - var compositeLifeCycleState = this._compositeLifeCycleState; - ("production" !== process.env.NODE_ENV ? invariant( - this.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING, - 'forceUpdate(...): Can only force an update on mounted or mounting ' + - 'components.' - ) : invariant(this.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); - ("production" !== process.env.NODE_ENV ? invariant( - compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && - ReactCurrentOwner.current == null, - 'forceUpdate(...): Cannot force an update while unmounting component ' + - 'or within a `render` function.' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && - ReactCurrentOwner.current == null)); - this._pendingForceUpdate = true; - ReactUpdates.enqueueUpdate(this, callback); + _replaceNodeWithMarkupByID: function(prevComponentID, nextMarkup) { + ReactComponentEnvironment.replaceNodeWithMarkupByID( + prevComponentID, + nextMarkup + ); }, /** - * @private + * @protected */ - _renderValidatedComponent: ReactPerf.measure( - 'ReactCompositeComponent', - '_renderValidatedComponent', - function() { - var renderedComponent; - var previousContext = ReactContext.current; - ReactContext.current = this._processChildContext( - this._currentElement._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; + _renderValidatedComponentWithoutOwnerOrContext: function() { + var inst = this._instance; + var renderedComponent = inst.render(); + if ("production" !== process.env.NODE_ENV) { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof renderedComponent === 'undefined' && + inst.render._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + renderedComponent = null; } - ("production" !== process.env.NODE_ENV ? invariant( - ReactElement.isValidElement(renderedComponent), - '%s.render(): A valid ReactComponent must be returned. You may have ' + - 'returned undefined, an array or some other invalid object.', - this.constructor.displayName || 'ReactCompositeComponent' - ) : invariant(ReactElement.isValidElement(renderedComponent))); - return renderedComponent; } - ), + + return renderedComponent; + }, /** * @private */ - _bindAutoBindMethods: function() { - for (var autoBindKey in this.__reactAutoBindMap) { - if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { - continue; - } - var method = this.__reactAutoBindMap[autoBindKey]; - this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard( - method, - this.constructor.displayName + '.' + autoBindKey - )); + _renderValidatedComponent: function() { + var renderedComponent; + var previousContext = ReactContext.current; + ReactContext.current = this._processChildContext( + this._currentElement._context + ); + ReactCurrentOwner.current = this; + try { + renderedComponent = + this._renderValidatedComponentWithoutOwnerOrContext(); + } finally { + ReactContext.current = previousContext; + ReactCurrentOwner.current = null; } + ("production" !== process.env.NODE_ENV ? invariant( + // TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || + ReactElement.isValidElement(renderedComponent), + '%s.render(): A valid ReactComponent must be returned. You may have ' + + 'returned undefined, an array or some other invalid object.', + this.getName() || 'ReactCompositeComponent' + ) : invariant(// TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || + ReactElement.isValidElement(renderedComponent))); + return renderedComponent; }, /** - * Binds a method to the component. + * Lazily allocates the refs object and stores `component` as `ref`. * - * @param {function} method Method to be bound. + * @param {string} ref Reference name. + * @param {component} component Component to store as `ref`. + * @final * @private */ - _bindAutoBindMethod: function(method) { - var component = this; - var boundMethod = method.bind(component); - if ("production" !== process.env.NODE_ENV) { - boundMethod.__reactBoundContext = component; - boundMethod.__reactBoundMethod = method; - boundMethod.__reactBoundArguments = null; - var componentName = component.constructor.displayName; - var _bind = boundMethod.bind; - boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1); - // User is trying to bind() an autobound method; we effectively will - // ignore the value of "this" that the user is trying to use, so - // let's warn. - if (newThis !== component && newThis !== null) { - monitorCodeUse('react_bind_warning', { component: componentName }); - console.warn( - 'bind(): React component methods may only be bound to the ' + - 'component instance. See ' + componentName - ); - } else if (!args.length) { - monitorCodeUse('react_bind_warning', { component: componentName }); - console.warn( - 'bind(): You are binding a component method to the component. ' + - 'React does this for you automatically in a high-performance ' + - 'way, so you can safely remove this call. See ' + componentName - ); - return boundMethod; - } - var reboundMethod = _bind.apply(boundMethod, arguments); - reboundMethod.__reactBoundContext = component; - reboundMethod.__reactBoundMethod = method; - reboundMethod.__reactBoundArguments = args; - return reboundMethod; - }; - } - return boundMethod; - } -}; - -var ReactCompositeComponentBase = function() {}; -assign( - ReactCompositeComponentBase.prototype, - ReactComponent.Mixin, - ReactOwner.Mixin, - ReactPropTransferer.Mixin, - ReactCompositeComponentMixin -); - -/** - * Module for creating composite components. - * - * @class ReactCompositeComponent - * @extends ReactComponent - * @extends ReactOwner - * @extends ReactPropTransferer - */ -var ReactCompositeComponent = { - - LifeCycle: CompositeLifeCycle, - - Base: ReactCompositeComponentBase, + attachRef: function(ref, component) { + var inst = this.getPublicInstance(); + var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; + refs[ref] = component.getPublicInstance(); + }, /** - * Creates a composite component class given a class specification. + * Detaches a reference name. * - * @param {object} spec Class specification (which must define `render`). - * @return {function} Component constructor function. - * @public + * @param {string} ref Name to dereference. + * @final + * @private */ - createClass: function(spec) { - var Constructor = function(props) { - // This constructor is overridden by mocks. The argument is used - // by mocks to assert on what gets mounted. This will later be used - // by the stand-alone class implementation. - }; - Constructor.prototype = new ReactCompositeComponentBase(); - Constructor.prototype.constructor = Constructor; + detachRef: function(ref) { + var refs = this.getPublicInstance().refs; + delete refs[ref]; + }, - injectedMixins.forEach( - mixSpecIntoComponent.bind(null, Constructor) + /** + * Get a text description of the component that can be used to identify it + * in error messages. + * @return {string} The name or null. + * @internal + */ + getName: function() { + var type = this._currentElement.type; + var constructor = this._instance && this._instance.constructor; + return ( + type.displayName || (constructor && constructor.displayName) || + type.name || (constructor && constructor.name) || + null ); + }, - mixSpecIntoComponent(Constructor, spec); + /** + * Get the publicly accessible representation of this component - i.e. what + * is exposed by refs and returned by React.render. Can be null for stateless + * components. + * + * @return {ReactComponent} the public component instance. + * @internal + */ + getPublicInstance: function() { + return this._instance; + }, - // Initialize the defaultProps property after all mixins have been merged - if (Constructor.getDefaultProps) { - Constructor.defaultProps = Constructor.getDefaultProps(); - } + // Stub + _instantiateReactComponent: null - ("production" !== process.env.NODE_ENV ? invariant( - Constructor.prototype.render, - 'createClass(...): Class specification must implement a `render` method.' - ) : invariant(Constructor.prototype.render)); +}; - if ("production" !== process.env.NODE_ENV) { - if (Constructor.prototype.componentShouldUpdate) { - monitorCodeUse( - 'react_component_should_update_warning', - { component: spec.displayName } - ); - console.warn( - (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.' - ); - } - } +ReactPerf.measureMethods( + ReactCompositeComponentMixin, + 'ReactCompositeComponent', + { + mountComponent: 'mountComponent', + updateComponent: 'updateComponent', + _renderValidatedComponent: '_renderValidatedComponent' + } +); - // 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 ReactCompositeComponent = { - if ("production" !== process.env.NODE_ENV) { - return ReactLegacyElement.wrapFactory( - ReactElementValidator.createFactory(Constructor) - ); - } - return ReactLegacyElement.wrapFactory( - ReactElement.createFactory(Constructor) - ); - }, + Mixin: ReactCompositeComponentMixin - injection: { - injectMixin: function(mixin) { - injectedMixins.push(mixin); - } - } }; module.exports = ReactCompositeComponent; }).call(this,require('_process')) -},{"./Object.assign":70,"./ReactComponent":78,"./ReactContext":82,"./ReactCurrentOwner":83,"./ReactElement":99,"./ReactElementValidator":100,"./ReactEmptyComponent":101,"./ReactErrorUtils":102,"./ReactLegacyElement":108,"./ReactOwner":115,"./ReactPerf":116,"./ReactPropTransferer":117,"./ReactPropTypeLocationNames":118,"./ReactPropTypeLocations":119,"./ReactUpdates":132,"./instantiateReactComponent":181,"./invariant":182,"./keyMirror":188,"./keyOf":189,"./mapObject":190,"./monitorCodeUse":192,"./shouldUpdateReactComponent":198,"./warning":202,"_process":1}],82:[function(require,module,exports){ +},{"./Object.assign":67,"./ReactComponentEnvironment":79,"./ReactContext":82,"./ReactCurrentOwner":83,"./ReactElement":101,"./ReactElementValidator":102,"./ReactInstanceMap":111,"./ReactLifeCycle":112,"./ReactNativeComponent":118,"./ReactPerf":120,"./ReactPropTypeLocationNames":122,"./ReactPropTypeLocations":123,"./ReactReconciler":127,"./ReactUpdates":138,"./emptyObject":169,"./invariant":189,"./shouldUpdateReactComponent":206,"./warning":210,"_process":1}],82:[function(require,module,exports){ +(function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -10338,9 +10733,13 @@ module.exports = ReactCompositeComponent; * @providesModule ReactContext */ -"use strict"; +'use strict'; var assign = require("./Object.assign"); +var emptyObject = require("./emptyObject"); +var warning = require("./warning"); + +var didWarn = false; /** * Keeps track of the current context. @@ -10354,7 +10753,7 @@ var ReactContext = { * @internal * @type {object} */ - current: {}, + current: emptyObject, /** * Temporarily extends the current context while executing scopedCallback. @@ -10373,6 +10772,16 @@ var ReactContext = { * @return {ReactComponent|array<ReactComponent>} */ withContext: function(newContext, scopedCallback) { + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + didWarn, + 'withContext is deprecated and will be removed in a future version. ' + + 'Use a wrapper component with getChildContext instead.' + ) : null); + + didWarn = true; + } + var result; var previousContext = ReactContext.current; ReactContext.current = assign({}, previousContext, newContext); @@ -10388,9 +10797,10 @@ var ReactContext = { module.exports = ReactContext; -},{"./Object.assign":70}],83:[function(require,module,exports){ +}).call(this,require('_process')) +},{"./Object.assign":67,"./emptyObject":169,"./warning":210,"_process":1}],83:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -10400,7 +10810,7 @@ module.exports = ReactContext; * @providesModule ReactCurrentOwner */ -"use strict"; +'use strict'; /** * Keeps track of the current owner. @@ -10425,7 +10835,7 @@ module.exports = ReactCurrentOwner; },{}],84:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -10436,11 +10846,10 @@ module.exports = ReactCurrentOwner; * @typechecks static-only */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); var ReactElementValidator = require("./ReactElementValidator"); -var ReactLegacyElement = require("./ReactLegacyElement"); var mapObject = require("./mapObject"); @@ -10452,13 +10861,9 @@ var mapObject = require("./mapObject"); */ function createDOMFactory(tag) { if ("production" !== process.env.NODE_ENV) { - return ReactLegacyElement.markNonLegacyFactory( - ReactElementValidator.createFactory(tag) - ); + return ReactElementValidator.createFactory(tag); } - return ReactLegacyElement.markNonLegacyFactory( - ReactElement.createFactory(tag) - ); + return ReactElement.createFactory(tag); } /** @@ -10605,9 +11010,9 @@ var ReactDOM = mapObject({ module.exports = ReactDOM; }).call(this,require('_process')) -},{"./ReactElement":99,"./ReactElementValidator":100,"./ReactLegacyElement":108,"./mapObject":190,"_process":1}],85:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactElementValidator":102,"./mapObject":197,"_process":1}],85:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -10617,18 +11022,16 @@ module.exports = ReactDOM; * @providesModule ReactDOMButton */ -"use strict"; +'use strict'; var AutoFocusMixin = require("./AutoFocusMixin"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); var keyMirror = require("./keyMirror"); -// Store a reference to the <button> `ReactDOMComponent`. TODO: use string -var button = ReactElement.createFactory(ReactDOM.button.type); +var button = ReactElement.createFactory('button'); var mouseListenerNames = keyMirror({ onClick: true, @@ -10647,8 +11050,9 @@ var mouseListenerNames = keyMirror({ * Implements a <button> native component that does not receive mouse events * when `disabled` is set. */ -var ReactDOMButton = ReactCompositeComponent.createClass({ +var ReactDOMButton = ReactClass.createClass({ displayName: 'ReactDOMButton', + tagName: 'BUTTON', mixins: [AutoFocusMixin, ReactBrowserComponentMixin], @@ -10670,10 +11074,10 @@ var ReactDOMButton = ReactCompositeComponent.createClass({ module.exports = ReactDOMButton; -},{"./AutoFocusMixin":43,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99,"./keyMirror":188}],86:[function(require,module,exports){ +},{"./AutoFocusMixin":40,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101,"./keyMirror":195}],86:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -10684,24 +11088,26 @@ module.exports = ReactDOMButton; * @typechecks static-only */ -"use strict"; +/* global hasOwnProperty:true */ + +'use strict'; var CSSPropertyOperations = require("./CSSPropertyOperations"); var DOMProperty = require("./DOMProperty"); var DOMPropertyOperations = require("./DOMPropertyOperations"); -var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactComponent = require("./ReactComponent"); var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); +var ReactComponentBrowserEnvironment = + require("./ReactComponentBrowserEnvironment"); var ReactMount = require("./ReactMount"); var ReactMultiChild = require("./ReactMultiChild"); var ReactPerf = require("./ReactPerf"); var assign = require("./Object.assign"); -var escapeTextForBrowser = require("./escapeTextForBrowser"); +var escapeTextContentForBrowser = require("./escapeTextContentForBrowser"); var invariant = require("./invariant"); var isEventSupported = require("./isEventSupported"); var keyOf = require("./keyOf"); -var monitorCodeUse = require("./monitorCodeUse"); +var warning = require("./warning"); var deleteListener = ReactBrowserEventEmitter.deleteListener; var listenTo = ReactBrowserEventEmitter.listenTo; @@ -10715,6 +11121,11 @@ var STYLE = keyOf({style: null}); var ELEMENT_NODE_TYPE = 1; /** + * Optionally injectable operations for mutating the DOM + */ +var BackendIDOperations = null; + +/** * @param {?object} props */ function assertValidProps(props) { @@ -10722,24 +11133,37 @@ function assertValidProps(props) { return; } // Note the use of `==` which checks for null or undefined. - ("production" !== process.env.NODE_ENV ? invariant( - props.children == null || props.dangerouslySetInnerHTML == null, - 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' - ) : invariant(props.children == null || props.dangerouslySetInnerHTML == null)); + if (props.dangerouslySetInnerHTML != null) { + ("production" !== process.env.NODE_ENV ? invariant( + props.children == null, + 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' + ) : invariant(props.children == null)); + ("production" !== process.env.NODE_ENV ? invariant( + props.dangerouslySetInnerHTML.__html != null, + '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + + 'Please visit http://fb.me/react-invariant-dangerously-set-inner-html ' + + 'for more information.' + ) : invariant(props.dangerouslySetInnerHTML.__html != null)); + } if ("production" !== process.env.NODE_ENV) { - if (props.contentEditable && props.children != null) { - console.warn( - 'A component is `contentEditable` and contains `children` managed by ' + - 'React. It is now your responsibility to guarantee that none of those '+ - 'nodes are unexpectedly modified or duplicated. This is probably not ' + - 'intentional.' - ); - } + ("production" !== process.env.NODE_ENV ? warning( + props.innerHTML == null, + 'Directly setting property `innerHTML` is not permitted. ' + + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.' + ) : null); + ("production" !== process.env.NODE_ENV ? warning( + !props.contentEditable || props.children == null, + 'A component is `contentEditable` and contains `children` managed by ' + + 'React. It is now your responsibility to guarantee that none of ' + + 'those nodes are unexpectedly modified or duplicated. This is ' + + 'probably not intentional.' + ) : null); } ("production" !== process.env.NODE_ENV ? invariant( props.style == null || typeof props.style === 'object', 'The `style` prop expects a mapping from style properties to values, ' + - 'not a string.' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + + 'using JSX.' ) : invariant(props.style == null || typeof props.style === 'object')); } @@ -10747,11 +11171,10 @@ function putListener(id, registrationName, listener, transaction) { if ("production" !== process.env.NODE_ENV) { // IE8 has no API for event capturing and the `onScroll` event doesn't // bubble. - if (registrationName === 'onScroll' && - !isEventSupported('scroll', true)) { - monitorCodeUse('react_no_scroll_event'); - console.warn('This browser doesn\'t support the `onScroll` event'); - } + ("production" !== process.env.NODE_ENV ? warning( + registrationName !== 'onScroll' || isEventSupported('scroll', true), + 'This browser doesn\'t support the `onScroll` event' + ) : null); } var container = ReactMount.findReactContainerForID(id); if (container) { @@ -10816,19 +11239,24 @@ function validateDangerousTag(tag) { * object mapping of style properties to values. * * @constructor ReactDOMComponent - * @extends ReactComponent * @extends ReactMultiChild */ function ReactDOMComponent(tag) { validateDangerousTag(tag); this._tag = tag; - this.tagName = tag.toUpperCase(); + this._renderedChildren = null; + this._previousStyleCopy = null; + this._rootNodeID = null; } ReactDOMComponent.displayName = 'ReactDOMComponent'; ReactDOMComponent.Mixin = { + construct: function(element) { + this._currentElement = element; + }, + /** * Generates root tag markup then recurses. This method has side effects and * is not idempotent. @@ -10836,28 +11264,18 @@ ReactDOMComponent.Mixin = { * @internal * @param {string} rootID The root DOM ID for this node. * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy * @return {string} The computed markup. */ - mountComponent: ReactPerf.measure( - 'ReactDOMComponent', - 'mountComponent', - function(rootID, transaction, mountDepth) { - ReactComponent.Mixin.mountComponent.call( - this, - rootID, - transaction, - mountDepth - ); - assertValidProps(this.props); - var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>'; - return ( - this._createOpenTagMarkupAndPutListeners(transaction) + - this._createContentMarkup(transaction) + - closeTag - ); - } - ), + mountComponent: function(rootID, transaction, context) { + this._rootNodeID = rootID; + assertValidProps(this._currentElement.props); + var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>'; + return ( + this._createOpenTagMarkupAndPutListeners(transaction) + + this._createContentMarkup(transaction, context) + + closeTag + ); + }, /** * Creates markup for the open tag and all attributes. @@ -10872,7 +11290,7 @@ ReactDOMComponent.Mixin = { * @return {string} Markup of opening tag. */ _createOpenTagMarkupAndPutListeners: function(transaction) { - var props = this.props; + var props = this._currentElement.props; var ret = '<' + this._tag; for (var propKey in props) { @@ -10888,7 +11306,7 @@ ReactDOMComponent.Mixin = { } else { if (propKey === STYLE) { if (propValue) { - propValue = props.style = assign({}, props.style); + propValue = this._previousStyleCopy = assign({}, props.style); } propValue = CSSPropertyOperations.createMarkupForStyles(propValue); } @@ -10915,50 +11333,50 @@ ReactDOMComponent.Mixin = { * * @private * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction + * @param {object} context * @return {string} Content markup. */ - _createContentMarkup: function(transaction) { + _createContentMarkup: function(transaction, context) { + var prefix = ''; + if (this._tag === 'listing' || + this._tag === 'pre' || + this._tag === 'textarea') { + // Add an initial newline because browsers ignore the first newline in + // a <listing>, <pre>, or <textarea> as an "authoring convenience" -- see + // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody. + prefix = '\n'; + } + + var props = this._currentElement.props; + // Intentional use of != to avoid catching zero/false. - var innerHTML = this.props.dangerouslySetInnerHTML; + var innerHTML = props.dangerouslySetInnerHTML; if (innerHTML != null) { if (innerHTML.__html != null) { - return innerHTML.__html; + return prefix + innerHTML.__html; } } else { var contentToUse = - CONTENT_TYPES[typeof this.props.children] ? this.props.children : null; - var childrenToUse = contentToUse != null ? null : this.props.children; + CONTENT_TYPES[typeof props.children] ? props.children : null; + var childrenToUse = contentToUse != null ? null : props.children; if (contentToUse != null) { - return escapeTextForBrowser(contentToUse); + return prefix + escapeTextContentForBrowser(contentToUse); } else if (childrenToUse != null) { var mountImages = this.mountChildren( childrenToUse, - transaction + transaction, + context ); - return mountImages.join(''); + return prefix + mountImages.join(''); } } - return ''; + return prefix; }, - receiveComponent: function(nextElement, transaction) { - if (nextElement === this._currentElement && - nextElement._owner != null) { - // Since elements 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 element. We explicitly check for the existence of an owner since - // it's possible for a element created outside a composite to be - // deeply mutated and reused. - return; - } - - ReactComponent.Mixin.receiveComponent.call( - this, - nextElement, - transaction - ); + receiveComponent: function(nextElement, transaction, context) { + var prevElement = this._currentElement; + this._currentElement = nextElement; + this.updateComponent(transaction, prevElement, nextElement, context); }, /** @@ -10967,23 +11385,15 @@ ReactDOMComponent.Mixin = { * * @param {ReactReconcileTransaction} transaction * @param {ReactElement} prevElement + * @param {ReactElement} nextElement * @internal * @overridable */ - updateComponent: ReactPerf.measure( - 'ReactDOMComponent', - 'updateComponent', - function(transaction, prevElement) { - assertValidProps(this._currentElement.props); - ReactComponent.Mixin.updateComponent.call( - this, - transaction, - prevElement - ); - this._updateDOMProperties(prevElement.props, transaction); - this._updateDOMChildren(prevElement.props, transaction); - } - ), + updateComponent: function(transaction, prevElement, nextElement, context) { + assertValidProps(this._currentElement.props); + this._updateDOMProperties(prevElement.props, transaction); + this._updateDOMChildren(prevElement.props, transaction, context); + }, /** * Reconciles the properties by detecting differences in property values and @@ -11001,7 +11411,7 @@ ReactDOMComponent.Mixin = { * @param {ReactReconcileTransaction} transaction */ _updateDOMProperties: function(lastProps, transaction) { - var nextProps = this.props; + var nextProps = this._currentElement.props; var propKey; var styleName; var styleUpdates; @@ -11011,19 +11421,20 @@ ReactDOMComponent.Mixin = { continue; } if (propKey === STYLE) { - var lastStyle = lastProps[propKey]; + var lastStyle = this._previousStyleCopy; for (styleName in lastStyle) { if (lastStyle.hasOwnProperty(styleName)) { styleUpdates = styleUpdates || {}; styleUpdates[styleName] = ''; } } + this._previousStyleCopy = null; } else if (registrationNameModules.hasOwnProperty(propKey)) { deleteListener(this._rootNodeID, propKey); } else if ( DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) { - ReactComponent.BackendIDOperations.deletePropertyByID( + BackendIDOperations.deletePropertyByID( this._rootNodeID, propKey ); @@ -11031,13 +11442,15 @@ ReactDOMComponent.Mixin = { } for (propKey in nextProps) { var nextProp = nextProps[propKey]; - var lastProp = lastProps[propKey]; + var lastProp = propKey === STYLE ? + this._previousStyleCopy : + lastProps[propKey]; if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) { continue; } if (propKey === STYLE) { if (nextProp) { - nextProp = nextProps.style = assign({}, nextProp); + nextProp = this._previousStyleCopy = assign({}, nextProp); } if (lastProp) { // Unset styles on `lastProp` but not on `nextProp`. @@ -11065,7 +11478,7 @@ ReactDOMComponent.Mixin = { } else if ( DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) { - ReactComponent.BackendIDOperations.updatePropertyByID( + BackendIDOperations.updatePropertyByID( this._rootNodeID, propKey, nextProp @@ -11073,7 +11486,7 @@ ReactDOMComponent.Mixin = { } } if (styleUpdates) { - ReactComponent.BackendIDOperations.updateStylesByID( + BackendIDOperations.updateStylesByID( this._rootNodeID, styleUpdates ); @@ -11087,8 +11500,8 @@ ReactDOMComponent.Mixin = { * @param {object} lastProps * @param {ReactReconcileTransaction} transaction */ - _updateDOMChildren: function(lastProps, transaction) { - var nextProps = this.props; + _updateDOMChildren: function(lastProps, transaction, context) { + var nextProps = this._currentElement.props; var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null; @@ -11111,7 +11524,7 @@ ReactDOMComponent.Mixin = { var lastHasContentOrHtml = lastContent != null || lastHtml != null; var nextHasContentOrHtml = nextContent != null || nextHtml != null; if (lastChildren != null && nextChildren == null) { - this.updateChildren(null, transaction); + this.updateChildren(null, transaction, context); } else if (lastHasContentOrHtml && !nextHasContentOrHtml) { this.updateTextContent(''); } @@ -11122,13 +11535,13 @@ ReactDOMComponent.Mixin = { } } else if (nextHtml != null) { if (lastHtml !== nextHtml) { - ReactComponent.BackendIDOperations.updateInnerHTMLByID( + BackendIDOperations.updateInnerHTMLByID( this._rootNodeID, nextHtml ); } } else if (nextChildren != null) { - this.updateChildren(nextChildren, transaction); + this.updateChildren(nextChildren, transaction, context); } }, @@ -11141,25 +11554,35 @@ ReactDOMComponent.Mixin = { unmountComponent: function() { this.unmountChildren(); ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID); - ReactComponent.Mixin.unmountComponent.call(this); + ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID); + this._rootNodeID = null; } }; +ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', { + mountComponent: 'mountComponent', + updateComponent: 'updateComponent' +}); + assign( ReactDOMComponent.prototype, - ReactComponent.Mixin, ReactDOMComponent.Mixin, - ReactMultiChild.Mixin, - ReactBrowserComponentMixin + ReactMultiChild.Mixin ); +ReactDOMComponent.injection = { + injectIDOperations: function(IDOperations) { + ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations; + } +}; + module.exports = ReactDOMComponent; }).call(this,require('_process')) -},{"./CSSPropertyOperations":47,"./DOMProperty":53,"./DOMPropertyOperations":54,"./Object.assign":70,"./ReactBrowserComponentMixin":73,"./ReactBrowserEventEmitter":74,"./ReactComponent":78,"./ReactMount":111,"./ReactMultiChild":112,"./ReactPerf":116,"./escapeTextForBrowser":165,"./invariant":182,"./isEventSupported":183,"./keyOf":189,"./monitorCodeUse":192,"_process":1}],87:[function(require,module,exports){ +},{"./CSSPropertyOperations":44,"./DOMProperty":49,"./DOMPropertyOperations":50,"./Object.assign":67,"./ReactBrowserEventEmitter":71,"./ReactComponentBrowserEnvironment":78,"./ReactMount":115,"./ReactMultiChild":116,"./ReactPerf":120,"./escapeTextContentForBrowser":170,"./invariant":189,"./isEventSupported":190,"./keyOf":196,"./warning":210,"_process":1}],87:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11169,17 +11592,15 @@ module.exports = ReactDOMComponent; * @providesModule ReactDOMForm */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var LocalEventTrapMixin = require("./LocalEventTrapMixin"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); -// Store a reference to the <form> `ReactDOMComponent`. TODO: use string -var form = ReactElement.createFactory(ReactDOM.form.type); +var form = ReactElement.createFactory('form'); /** * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need @@ -11187,8 +11608,9 @@ var form = ReactElement.createFactory(ReactDOM.form.type); * 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({ +var ReactDOMForm = ReactClass.createClass({ displayName: 'ReactDOMForm', + tagName: 'FORM', mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin], @@ -11207,10 +11629,10 @@ var ReactDOMForm = ReactCompositeComponent.createClass({ module.exports = ReactDOMForm; -},{"./EventConstants":58,"./LocalEventTrapMixin":68,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99}],88:[function(require,module,exports){ +},{"./EventConstants":54,"./LocalEventTrapMixin":65,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101}],88:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11223,7 +11645,7 @@ module.exports = ReactDOMForm; /*jslint evil: true */ -"use strict"; +'use strict'; var CSSPropertyOperations = require("./CSSPropertyOperations"); var DOMChildrenOperations = require("./DOMChildrenOperations"); @@ -11248,7 +11670,7 @@ var INVALID_PROPERTY_ERRORS = { /** * Operations used to process updates to DOM nodes. This is made injectable via - * `ReactComponent.BackendIDOperations`. + * `ReactDOMComponent.BackendIDOperations`. */ var ReactDOMIDOperations = { @@ -11261,27 +11683,23 @@ var ReactDOMIDOperations = { * @param {*} value New value of the property. * @internal */ - updatePropertyByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'updatePropertyByID', - function(id, name, value) { - var node = ReactMount.getNode(id); - ("production" !== process.env.NODE_ENV ? invariant( - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), - 'updatePropertyByID(...): %s', - INVALID_PROPERTY_ERRORS[name] - ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); - - // If we're updating to null or undefined, we should remove the property - // from the DOM node instead of inadvertantly setting to a string. This - // brings us in line with the same behavior we have on initial render. - if (value != null) { - DOMPropertyOperations.setValueForProperty(node, name, value); - } else { - DOMPropertyOperations.deleteValueForProperty(node, name); - } + updatePropertyByID: function(id, name, value) { + var node = ReactMount.getNode(id); + ("production" !== process.env.NODE_ENV ? invariant( + !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), + 'updatePropertyByID(...): %s', + INVALID_PROPERTY_ERRORS[name] + ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); + + // If we're updating to null or undefined, we should remove the property + // from the DOM node instead of inadvertantly setting to a string. This + // brings us in line with the same behavior we have on initial render. + if (value != null) { + DOMPropertyOperations.setValueForProperty(node, name, value); + } else { + DOMPropertyOperations.deleteValueForProperty(node, name); } - ), + }, /** * Updates a DOM node to remove a property. This should only be used to remove @@ -11291,19 +11709,15 @@ var ReactDOMIDOperations = { * @param {string} name A property name to remove, see `DOMProperty`. * @internal */ - deletePropertyByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'deletePropertyByID', - function(id, name, value) { - var node = ReactMount.getNode(id); - ("production" !== process.env.NODE_ENV ? invariant( - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), - 'updatePropertyByID(...): %s', - INVALID_PROPERTY_ERRORS[name] - ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); - DOMPropertyOperations.deleteValueForProperty(node, name, value); - } - ), + deletePropertyByID: function(id, name, value) { + var node = ReactMount.getNode(id); + ("production" !== process.env.NODE_ENV ? invariant( + !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), + 'updatePropertyByID(...): %s', + INVALID_PROPERTY_ERRORS[name] + ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); + DOMPropertyOperations.deleteValueForProperty(node, name, value); + }, /** * Updates a DOM node with new style values. If a value is specified as '', @@ -11313,14 +11727,10 @@ var ReactDOMIDOperations = { * @param {object} styles Mapping from styles to values. * @internal */ - updateStylesByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'updateStylesByID', - function(id, styles) { - var node = ReactMount.getNode(id); - CSSPropertyOperations.setValueForStyles(node, styles); - } - ), + updateStylesByID: function(id, styles) { + var node = ReactMount.getNode(id); + CSSPropertyOperations.setValueForStyles(node, styles); + }, /** * Updates a DOM node's innerHTML. @@ -11329,14 +11739,10 @@ var ReactDOMIDOperations = { * @param {string} html An HTML string. * @internal */ - updateInnerHTMLByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'updateInnerHTMLByID', - function(id, html) { - var node = ReactMount.getNode(id); - setInnerHTML(node, html); - } - ), + updateInnerHTMLByID: function(id, html) { + var node = ReactMount.getNode(id); + setInnerHTML(node, html); + }, /** * Updates a DOM node's text content set by `props.content`. @@ -11345,14 +11751,10 @@ var ReactDOMIDOperations = { * @param {string} content Text content. * @internal */ - updateTextContentByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'updateTextContentByID', - function(id, content) { - var node = ReactMount.getNode(id); - DOMChildrenOperations.updateTextContent(node, content); - } - ), + updateTextContentByID: function(id, content) { + var node = ReactMount.getNode(id); + DOMChildrenOperations.updateTextContent(node, content); + }, /** * Replaces a DOM node that exists in the document with markup. @@ -11362,14 +11764,10 @@ var ReactDOMIDOperations = { * @internal * @see {Danger.dangerouslyReplaceNodeWithMarkup} */ - dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'dangerouslyReplaceNodeWithMarkupByID', - function(id, markup) { - var node = ReactMount.getNode(id); - DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); - } - ), + dangerouslyReplaceNodeWithMarkupByID: function(id, markup) { + var node = ReactMount.getNode(id); + DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); + }, /** * Updates a component's children by processing a series of updates. @@ -11378,24 +11776,75 @@ var ReactDOMIDOperations = { * @param {array<string>} markup List of markup strings. * @internal */ - dangerouslyProcessChildrenUpdates: ReactPerf.measure( - 'ReactDOMIDOperations', - 'dangerouslyProcessChildrenUpdates', - function(updates, markup) { - for (var i = 0; i < updates.length; i++) { - updates[i].parentNode = ReactMount.getNode(updates[i].parentID); - } - DOMChildrenOperations.processUpdates(updates, markup); + dangerouslyProcessChildrenUpdates: function(updates, markup) { + for (var i = 0; i < updates.length; i++) { + updates[i].parentNode = ReactMount.getNode(updates[i].parentID); } - ) + DOMChildrenOperations.processUpdates(updates, markup); + } }; +ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', { + updatePropertyByID: 'updatePropertyByID', + deletePropertyByID: 'deletePropertyByID', + updateStylesByID: 'updateStylesByID', + updateInnerHTMLByID: 'updateInnerHTMLByID', + updateTextContentByID: 'updateTextContentByID', + dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID', + dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates' +}); + module.exports = ReactDOMIDOperations; }).call(this,require('_process')) -},{"./CSSPropertyOperations":47,"./DOMChildrenOperations":52,"./DOMPropertyOperations":54,"./ReactMount":111,"./ReactPerf":116,"./invariant":182,"./setInnerHTML":196,"_process":1}],89:[function(require,module,exports){ +},{"./CSSPropertyOperations":44,"./DOMChildrenOperations":48,"./DOMPropertyOperations":50,"./ReactMount":115,"./ReactPerf":120,"./invariant":189,"./setInnerHTML":203,"_process":1}],89:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOMIframe + */ + +'use strict'; + +var EventConstants = require("./EventConstants"); +var LocalEventTrapMixin = require("./LocalEventTrapMixin"); +var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); +var ReactClass = require("./ReactClass"); +var ReactElement = require("./ReactElement"); + +var iframe = ReactElement.createFactory('iframe'); + +/** + * Since onLoad doesn't bubble OR capture on the top level in IE8, we need to + * capture it on the <iframe> element itself. There are lots of hacks we could + * do to accomplish this, but the most reliable is to make <iframe> a composite + * component and use `componentDidMount` to attach the event handlers. + */ +var ReactDOMIframe = ReactClass.createClass({ + displayName: 'ReactDOMIframe', + tagName: 'IFRAME', + + mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin], + + render: function() { + return iframe(this.props); + }, + + componentDidMount: function() { + this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load'); + } +}); + +module.exports = ReactDOMIframe; + +},{"./EventConstants":54,"./LocalEventTrapMixin":65,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101}],90:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11405,17 +11854,15 @@ module.exports = ReactDOMIDOperations; * @providesModule ReactDOMImg */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var LocalEventTrapMixin = require("./LocalEventTrapMixin"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); -// Store a reference to the <img> `ReactDOMComponent`. TODO: use string -var img = ReactElement.createFactory(ReactDOM.img.type); +var img = ReactElement.createFactory('img'); /** * Since onLoad doesn't bubble OR capture on the top level in IE8, we need to @@ -11423,7 +11870,7 @@ var img = ReactElement.createFactory(ReactDOM.img.type); * 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({ +var ReactDOMImg = ReactClass.createClass({ displayName: 'ReactDOMImg', tagName: 'IMG', @@ -11441,10 +11888,10 @@ var ReactDOMImg = ReactCompositeComponent.createClass({ module.exports = ReactDOMImg; -},{"./EventConstants":58,"./LocalEventTrapMixin":68,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99}],90:[function(require,module,exports){ +},{"./EventConstants":54,"./LocalEventTrapMixin":65,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101}],91:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11454,23 +11901,21 @@ module.exports = ReactDOMImg; * @providesModule ReactDOMInput */ -"use strict"; +'use strict'; var AutoFocusMixin = require("./AutoFocusMixin"); var DOMPropertyOperations = require("./DOMPropertyOperations"); var LinkedValueUtils = require("./LinkedValueUtils"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); var ReactMount = require("./ReactMount"); var ReactUpdates = require("./ReactUpdates"); var assign = require("./Object.assign"); var invariant = require("./invariant"); -// Store a reference to the <input> `ReactDOMComponent`. TODO: use string -var input = ReactElement.createFactory(ReactDOM.input.type); +var input = ReactElement.createFactory('input'); var instancesByReactID = {}; @@ -11497,8 +11942,9 @@ function forceUpdateIfMounted() { * * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html */ -var ReactDOMInput = ReactCompositeComponent.createClass({ +var ReactDOMInput = ReactClass.createClass({ displayName: 'ReactDOMInput', + tagName: 'INPUT', mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], @@ -11619,10 +12065,10 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ module.exports = ReactDOMInput; }).call(this,require('_process')) -},{"./AutoFocusMixin":43,"./DOMPropertyOperations":54,"./LinkedValueUtils":67,"./Object.assign":70,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99,"./ReactMount":111,"./ReactUpdates":132,"./invariant":182,"_process":1}],91:[function(require,module,exports){ +},{"./AutoFocusMixin":40,"./DOMPropertyOperations":50,"./LinkedValueUtils":64,"./Object.assign":67,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101,"./ReactMount":115,"./ReactUpdates":138,"./invariant":189,"_process":1}],92:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11632,23 +12078,22 @@ module.exports = ReactDOMInput; * @providesModule ReactDOMOption */ -"use strict"; +'use strict'; var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); var warning = require("./warning"); -// Store a reference to the <option> `ReactDOMComponent`. TODO: use string -var option = ReactElement.createFactory(ReactDOM.option.type); +var option = ReactElement.createFactory('option'); /** * Implements an <option> native component that warns when `selected` is set. */ -var ReactDOMOption = ReactCompositeComponent.createClass({ +var ReactDOMOption = ReactClass.createClass({ displayName: 'ReactDOMOption', + tagName: 'OPTION', mixins: [ReactBrowserComponentMixin], @@ -11672,9 +12117,9 @@ var ReactDOMOption = ReactCompositeComponent.createClass({ module.exports = ReactDOMOption; }).call(this,require('_process')) -},{"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99,"./warning":202,"_process":1}],92:[function(require,module,exports){ +},{"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101,"./warning":210,"_process":1}],93:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11684,26 +12129,27 @@ module.exports = ReactDOMOption; * @providesModule ReactDOMSelect */ -"use strict"; +'use strict'; var AutoFocusMixin = require("./AutoFocusMixin"); var LinkedValueUtils = require("./LinkedValueUtils"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); var ReactUpdates = require("./ReactUpdates"); var assign = require("./Object.assign"); -// Store a reference to the <select> `ReactDOMComponent`. TODO: use string -var select = ReactElement.createFactory(ReactDOM.select.type); +var select = ReactElement.createFactory('select'); -function updateWithPendingValueIfMounted() { +function updateOptionsIfPendingUpdateAndMounted() { /*jshint validthis:true */ - if (this.isMounted()) { - this.setState({value: this._pendingValue}); - this._pendingValue = 0; + if (this._pendingUpdate) { + this._pendingUpdate = false; + var value = LinkedValueUtils.getValue(this); + if (value != null && this.isMounted()) { + updateOptions(this, value); + } } } @@ -11713,7 +12159,7 @@ function updateWithPendingValueIfMounted() { */ function selectValueType(props, propName, componentName) { if (props[propName] == null) { - return; + return null; } if (props.multiple) { if (!Array.isArray(props[propName])) { @@ -11733,32 +12179,37 @@ function selectValueType(props, propName, componentName) { } /** - * 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). + * @param {*} propValue A stringable (with `multiple`, a list of stringables). * @private */ function updateOptions(component, propValue) { - var multiple = component.props.multiple; - var value = propValue != null ? propValue : component.state.value; - var options = component.getDOMNode().options; var selectedValue, i, l; - if (multiple) { + var options = component.getDOMNode().options; + + if (component.props.multiple) { selectedValue = {}; - for (i = 0, l = value.length; i < l; ++i) { - selectedValue['' + value[i]] = true; + for (i = 0, l = propValue.length; i < l; i++) { + selectedValue['' + propValue[i]] = true; + } + for (i = 0, l = options.length; i < l; i++) { + var selected = selectedValue.hasOwnProperty(options[i].value); + if (options[i].selected !== selected) { + options[i].selected = selected; + } } } else { - selectedValue = '' + value; - } - for (i = 0, l = options.length; i < l; i++) { - var selected = multiple ? - selectedValue.hasOwnProperty(options[i].value) : - options[i].value === selectedValue; - - if (selected !== options[i].selected) { - options[i].selected = selected; + // Do not set `select.value` as exact behavior isn't consistent across all + // browsers for all cases. + selectedValue = '' + propValue; + for (i = 0, l = options.length; i < l; i++) { + if (options[i].value === selectedValue) { + options[i].selected = true; + return; + } + } + if (options.length) { + options[0].selected = true; } } } @@ -11766,7 +12217,7 @@ function updateOptions(component, propValue) { /** * Implements a <select> native component that allows optionally setting the * props `value` and `defaultValue`. If `multiple` is false, the prop must be a - * string. If `multiple` is true, the prop must be an array of strings. + * stringable. If `multiple` is true, the prop must be an array of stringables. * * If `value` is not supplied (or null/undefined), user actions that change the * selected option will trigger updates to the rendered options. @@ -11778,8 +12229,9 @@ function updateOptions(component, propValue) { * If `defaultValue` is provided, any options with the supplied values will be * selected. */ -var ReactDOMSelect = ReactCompositeComponent.createClass({ +var ReactDOMSelect = ReactClass.createClass({ displayName: 'ReactDOMSelect', + tagName: 'SELECT', mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], @@ -11788,22 +12240,6 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ value: selectValueType }, - getInitialState: function() { - return {value: this.props.defaultValue || (this.props.multiple ? [] : '')}; - }, - - componentWillMount: function() { - this._pendingValue = null; - }, - - componentWillReceiveProps: function(nextProps) { - if (!this.props.multiple && nextProps.multiple) { - this.setState({value: [this.state.value]}); - } else if (this.props.multiple && !nextProps.multiple) { - this.setState({value: this.state.value[0]}); - } - }, - render: function() { // Clone `this.props` so we don't mutate the input. var props = assign({}, this.props); @@ -11814,16 +12250,32 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ return select(props, this.props.children); }, + componentWillMount: function() { + this._pendingUpdate = false; + }, + componentDidMount: function() { - updateOptions(this, LinkedValueUtils.getValue(this)); + var value = LinkedValueUtils.getValue(this); + if (value != null) { + updateOptions(this, value); + } else if (this.props.defaultValue != null) { + updateOptions(this, this.props.defaultValue); + } }, componentDidUpdate: function(prevProps) { var value = LinkedValueUtils.getValue(this); - var prevMultiple = !!prevProps.multiple; - var multiple = !!this.props.multiple; - if (value != null || prevMultiple !== multiple) { + if (value != null) { + this._pendingUpdate = false; updateOptions(this, value); + } else if (!prevProps.multiple !== !this.props.multiple) { + // For simplicity, reapply `defaultValue` if `multiple` is toggled. + if (this.props.defaultValue != null) { + updateOptions(this, this.props.defaultValue); + } else { + // Revert the select back to its default unselected state. + updateOptions(this, this.props.multiple ? [] : ''); + } } }, @@ -11834,21 +12286,8 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ returnValue = onChange.call(this, event); } - var selectedValue; - if (this.props.multiple) { - selectedValue = []; - var options = event.target.options; - for (var i = 0, l = options.length; i < l; i++) { - if (options[i].selected) { - selectedValue.push(options[i].value); - } - } - } else { - selectedValue = event.target.value; - } - - this._pendingValue = selectedValue; - ReactUpdates.asap(updateWithPendingValueIfMounted, this); + this._pendingUpdate = true; + ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this); return returnValue; } @@ -11856,9 +12295,9 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ module.exports = ReactDOMSelect; -},{"./AutoFocusMixin":43,"./LinkedValueUtils":67,"./Object.assign":70,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99,"./ReactUpdates":132}],93:[function(require,module,exports){ +},{"./AutoFocusMixin":40,"./LinkedValueUtils":64,"./Object.assign":67,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101,"./ReactUpdates":138}],94:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -11868,7 +12307,7 @@ module.exports = ReactDOMSelect; * @providesModule ReactDOMSelection */ -"use strict"; +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -12048,7 +12487,11 @@ function setModernOffsets(node, offsets) { } } -var useIEOffsets = ExecutionEnvironment.canUseDOM && document.selection; +var useIEOffsets = ( + ExecutionEnvironment.canUseDOM && + 'selection' in document && + !('getSelection' in window) +); var ReactDOMSelection = { /** @@ -12065,10 +12508,127 @@ var ReactDOMSelection = { module.exports = ReactDOMSelection; -},{"./ExecutionEnvironment":64,"./getNodeForCharacterOffset":175,"./getTextContentAccessor":177}],94:[function(require,module,exports){ +},{"./ExecutionEnvironment":60,"./getNodeForCharacterOffset":182,"./getTextContentAccessor":184}],95:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOMTextComponent + * @typechecks static-only + */ + +'use strict'; + +var DOMPropertyOperations = require("./DOMPropertyOperations"); +var ReactComponentBrowserEnvironment = + require("./ReactComponentBrowserEnvironment"); +var ReactDOMComponent = require("./ReactDOMComponent"); + +var assign = require("./Object.assign"); +var escapeTextContentForBrowser = require("./escapeTextContentForBrowser"); + +/** + * Text nodes violate a couple assumptions that React makes about components: + * + * - When mounting text into the DOM, adjacent text nodes are merged. + * - Text nodes cannot be assigned a React root ID. + * + * This component is used to wrap strings in elements so that they can undergo + * the same reconciliation that is applied to elements. + * + * TODO: Investigate representing React components in the DOM with text nodes. + * + * @class ReactDOMTextComponent + * @extends ReactComponent + * @internal + */ +var ReactDOMTextComponent = function(props) { + // This constructor and its argument is currently used by mocks. +}; + +assign(ReactDOMTextComponent.prototype, { + + /** + * @param {ReactText} text + * @internal + */ + construct: function(text) { + // TODO: This is really a ReactText (ReactNode), not a ReactElement + this._currentElement = text; + this._stringText = '' + text; + + // Properties + this._rootNodeID = null; + this._mountIndex = 0; + }, + + /** + * Creates the markup for this text node. This node is not intended to have + * any features besides containing text content. + * + * @param {string} rootID DOM ID of the root node. + * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction + * @return {string} Markup for this text node. + * @internal + */ + mountComponent: function(rootID, transaction, context) { + this._rootNodeID = rootID; + var escapedText = escapeTextContentForBrowser(this._stringText); + + if (transaction.renderToStaticMarkup) { + // Normally we'd wrap this in a `span` for the reasons stated above, but + // since this is a situation where React won't take over (static pages), + // we can simply return the text as it is. + return escapedText; + } + + return ( + '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' + + escapedText + + '</span>' + ); + }, + + /** + * Updates this component by updating the text content. + * + * @param {ReactText} nextText The next text content + * @param {ReactReconcileTransaction} transaction + * @internal + */ + receiveComponent: function(nextText, transaction) { + if (nextText !== this._currentElement) { + this._currentElement = nextText; + var nextStringText = '' + nextText; + if (nextStringText !== this._stringText) { + // TODO: Save this as pending props and use performUpdateIfNecessary + // and/or updateComponent to do the actual update for consistency with + // other component types? + this._stringText = nextStringText; + ReactDOMComponent.BackendIDOperations.updateTextContentByID( + this._rootNodeID, + nextStringText + ); + } + } + }, + + unmountComponent: function() { + ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID); + } + +}); + +module.exports = ReactDOMTextComponent; + +},{"./DOMPropertyOperations":50,"./Object.assign":67,"./ReactComponentBrowserEnvironment":78,"./ReactDOMComponent":86,"./escapeTextContentForBrowser":170}],96:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12078,15 +12638,14 @@ module.exports = ReactDOMSelection; * @providesModule ReactDOMTextarea */ -"use strict"; +'use strict'; var AutoFocusMixin = require("./AutoFocusMixin"); var DOMPropertyOperations = require("./DOMPropertyOperations"); var LinkedValueUtils = require("./LinkedValueUtils"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); -var ReactDOM = require("./ReactDOM"); var ReactUpdates = require("./ReactUpdates"); var assign = require("./Object.assign"); @@ -12094,8 +12653,7 @@ var invariant = require("./invariant"); var warning = require("./warning"); -// Store a reference to the <textarea> `ReactDOMComponent`. TODO: use string -var textarea = ReactElement.createFactory(ReactDOM.textarea.type); +var textarea = ReactElement.createFactory('textarea'); function forceUpdateIfMounted() { /*jshint validthis:true */ @@ -12119,8 +12677,9 @@ function forceUpdateIfMounted() { * The rendered element will be initialized with an empty value, the prop * `defaultValue` if specified, or the children content (deprecated). */ -var ReactDOMTextarea = ReactCompositeComponent.createClass({ +var ReactDOMTextarea = ReactClass.createClass({ displayName: 'ReactDOMTextarea', + tagName: 'TEXTAREA', mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], @@ -12206,9 +12765,9 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ module.exports = ReactDOMTextarea; }).call(this,require('_process')) -},{"./AutoFocusMixin":43,"./DOMPropertyOperations":54,"./LinkedValueUtils":67,"./Object.assign":70,"./ReactBrowserComponentMixin":73,"./ReactCompositeComponent":81,"./ReactDOM":84,"./ReactElement":99,"./ReactUpdates":132,"./invariant":182,"./warning":202,"_process":1}],95:[function(require,module,exports){ +},{"./AutoFocusMixin":40,"./DOMPropertyOperations":50,"./LinkedValueUtils":64,"./Object.assign":67,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactElement":101,"./ReactUpdates":138,"./invariant":189,"./warning":210,"_process":1}],97:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12218,7 +12777,7 @@ module.exports = ReactDOMTextarea; * @providesModule ReactDefaultBatchingStrategy */ -"use strict"; +'use strict'; var ReactUpdates = require("./ReactUpdates"); var Transaction = require("./Transaction"); @@ -12263,26 +12822,26 @@ var ReactDefaultBatchingStrategy = { * 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, a, b) { + batchedUpdates: function(callback, a, b, c, d) { var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates; ReactDefaultBatchingStrategy.isBatchingUpdates = true; // The code is written this way to avoid extra allocations if (alreadyBatchingUpdates) { - callback(a, b); + callback(a, b, c, d); } else { - transaction.perform(callback, null, a, b); + transaction.perform(callback, null, a, b, c, d); } } }; module.exports = ReactDefaultBatchingStrategy; -},{"./Object.assign":70,"./ReactUpdates":132,"./Transaction":149,"./emptyFunction":163}],96:[function(require,module,exports){ +},{"./Object.assign":67,"./ReactUpdates":138,"./Transaction":155,"./emptyFunction":168}],98:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12292,18 +12851,18 @@ module.exports = ReactDefaultBatchingStrategy; * @providesModule ReactDefaultInjection */ -"use strict"; +'use strict'; var BeforeInputEventPlugin = require("./BeforeInputEventPlugin"); var ChangeEventPlugin = require("./ChangeEventPlugin"); var ClientReactRootIndex = require("./ClientReactRootIndex"); -var CompositionEventPlugin = require("./CompositionEventPlugin"); var DefaultEventPluginOrder = require("./DefaultEventPluginOrder"); var EnterLeaveEventPlugin = require("./EnterLeaveEventPlugin"); var ExecutionEnvironment = require("./ExecutionEnvironment"); var HTMLDOMPropertyConfig = require("./HTMLDOMPropertyConfig"); var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin"); var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); +var ReactClass = require("./ReactClass"); var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment"); var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy"); @@ -12311,14 +12870,19 @@ var ReactDOMComponent = require("./ReactDOMComponent"); var ReactDOMButton = require("./ReactDOMButton"); var ReactDOMForm = require("./ReactDOMForm"); var ReactDOMImg = require("./ReactDOMImg"); +var ReactDOMIDOperations = require("./ReactDOMIDOperations"); +var ReactDOMIframe = require("./ReactDOMIframe"); var ReactDOMInput = require("./ReactDOMInput"); var ReactDOMOption = require("./ReactDOMOption"); var ReactDOMSelect = require("./ReactDOMSelect"); var ReactDOMTextarea = require("./ReactDOMTextarea"); +var ReactDOMTextComponent = require("./ReactDOMTextComponent"); +var ReactElement = require("./ReactElement"); var ReactEventListener = require("./ReactEventListener"); var ReactInjection = require("./ReactInjection"); var ReactInstanceHandles = require("./ReactInstanceHandles"); var ReactMount = require("./ReactMount"); +var ReactReconcileTransaction = require("./ReactReconcileTransaction"); var SelectEventPlugin = require("./SelectEventPlugin"); var ServerReactRootIndex = require("./ServerReactRootIndex"); var SimpleEventPlugin = require("./SimpleEventPlugin"); @@ -12326,6 +12890,22 @@ var SVGDOMPropertyConfig = require("./SVGDOMPropertyConfig"); var createFullPageComponent = require("./createFullPageComponent"); +function autoGenerateWrapperClass(type) { + return ReactClass.createClass({ + tagName: type.toUpperCase(), + render: function() { + return new ReactElement( + type, + null, + null, + null, + null, + this.props + ); + } + }); +} + function inject() { ReactInjection.EventEmitter.injectReactEventListener( ReactEventListener @@ -12346,7 +12926,6 @@ function inject() { SimpleEventPlugin: SimpleEventPlugin, EnterLeaveEventPlugin: EnterLeaveEventPlugin, ChangeEventPlugin: ChangeEventPlugin, - CompositionEventPlugin: CompositionEventPlugin, MobileSafariClickEventPlugin: MobileSafariClickEventPlugin, SelectEventPlugin: SelectEventPlugin, BeforeInputEventPlugin: BeforeInputEventPlugin @@ -12356,9 +12935,22 @@ function inject() { ReactDOMComponent ); + ReactInjection.NativeComponent.injectTextComponentClass( + ReactDOMTextComponent + ); + + ReactInjection.NativeComponent.injectAutoWrapper( + autoGenerateWrapperClass + ); + + // This needs to happen before createFullPageComponent() otherwise the mixin + // won't be included. + ReactInjection.Class.injectMixin(ReactBrowserComponentMixin); + ReactInjection.NativeComponent.injectComponentClasses({ 'button': ReactDOMButton, 'form': ReactDOMForm, + 'iframe': ReactDOMIframe, 'img': ReactDOMImg, 'input': ReactDOMInput, 'option': ReactDOMOption, @@ -12370,17 +12962,13 @@ function inject() { 'body': createFullPageComponent('body') }); - // This needs to happen after createFullPageComponent() otherwise the mixin - // gets double injected. - ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin); - ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig); ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig); ReactInjection.EmptyComponent.injectEmptyComponent('noscript'); ReactInjection.Updates.injectReconcileTransaction( - ReactComponentBrowserEnvironment.ReactReconcileTransaction + ReactReconcileTransaction ); ReactInjection.Updates.injectBatchingStrategy( ReactDefaultBatchingStrategy @@ -12393,6 +12981,7 @@ function inject() { ); ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment); + ReactInjection.DOMComponent.injectIDOperations(ReactDOMIDOperations); if ("production" !== process.env.NODE_ENV) { var url = (ExecutionEnvironment.canUseDOM && window.location.href) || ''; @@ -12408,9 +12997,9 @@ module.exports = { }; }).call(this,require('_process')) -},{"./BeforeInputEventPlugin":44,"./ChangeEventPlugin":49,"./ClientReactRootIndex":50,"./CompositionEventPlugin":51,"./DefaultEventPluginOrder":56,"./EnterLeaveEventPlugin":57,"./ExecutionEnvironment":64,"./HTMLDOMPropertyConfig":65,"./MobileSafariClickEventPlugin":69,"./ReactBrowserComponentMixin":73,"./ReactComponentBrowserEnvironment":79,"./ReactDOMButton":85,"./ReactDOMComponent":86,"./ReactDOMForm":87,"./ReactDOMImg":89,"./ReactDOMInput":90,"./ReactDOMOption":91,"./ReactDOMSelect":92,"./ReactDOMTextarea":94,"./ReactDefaultBatchingStrategy":95,"./ReactDefaultPerf":97,"./ReactEventListener":104,"./ReactInjection":105,"./ReactInstanceHandles":107,"./ReactMount":111,"./SVGDOMPropertyConfig":134,"./SelectEventPlugin":135,"./ServerReactRootIndex":136,"./SimpleEventPlugin":137,"./createFullPageComponent":158,"_process":1}],97:[function(require,module,exports){ +},{"./BeforeInputEventPlugin":41,"./ChangeEventPlugin":46,"./ClientReactRootIndex":47,"./DefaultEventPluginOrder":52,"./EnterLeaveEventPlugin":53,"./ExecutionEnvironment":60,"./HTMLDOMPropertyConfig":62,"./MobileSafariClickEventPlugin":66,"./ReactBrowserComponentMixin":70,"./ReactClass":76,"./ReactComponentBrowserEnvironment":78,"./ReactDOMButton":85,"./ReactDOMComponent":86,"./ReactDOMForm":87,"./ReactDOMIDOperations":88,"./ReactDOMIframe":89,"./ReactDOMImg":90,"./ReactDOMInput":91,"./ReactDOMOption":92,"./ReactDOMSelect":93,"./ReactDOMTextComponent":95,"./ReactDOMTextarea":96,"./ReactDefaultBatchingStrategy":97,"./ReactDefaultPerf":99,"./ReactElement":101,"./ReactEventListener":106,"./ReactInjection":108,"./ReactInstanceHandles":110,"./ReactMount":115,"./ReactReconcileTransaction":126,"./SVGDOMPropertyConfig":140,"./SelectEventPlugin":141,"./ServerReactRootIndex":142,"./SimpleEventPlugin":143,"./createFullPageComponent":164,"_process":1}],99:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12421,7 +13010,7 @@ module.exports = { * @typechecks static-only */ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); var ReactDefaultPerfAnalysis = require("./ReactDefaultPerfAnalysis"); @@ -12548,7 +13137,7 @@ var ReactDefaultPerf = { }, measure: function(moduleName, fnName, func) { - return function() {var args=Array.prototype.slice.call(arguments,0); + return function() {for (var args=[],$__0=0,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); var totalTime; var rv; var start; @@ -12574,13 +13163,13 @@ var ReactDefaultPerf = { ReactDefaultPerf._allMeasurements.length - 1 ].totalTime = performanceNow() - start; return rv; - } else if (moduleName === 'ReactDOMIDOperations' || - moduleName === 'ReactComponentBrowserEnvironment') { + } else if (fnName === '_mountImageIntoNode' || + moduleName === 'ReactDOMIDOperations') { start = performanceNow(); rv = func.apply(this, args); totalTime = performanceNow() - start; - if (fnName === 'mountImageIntoNode') { + if (fnName === '_mountImageIntoNode') { var mountID = ReactMount.getID(args[1]); ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]); } else if (fnName === 'dangerouslyProcessChildrenUpdates') { @@ -12617,9 +13206,13 @@ var ReactDefaultPerf = { } return rv; } else if (moduleName === 'ReactCompositeComponent' && ( - fnName === 'mountComponent' || - fnName === 'updateComponent' || // TODO: receiveComponent()? - fnName === '_renderValidatedComponent')) { + (// TODO: receiveComponent()? + (fnName === 'mountComponent' || + fnName === 'updateComponent' || fnName === '_renderValidatedComponent')))) { + + if (typeof this._currentElement.type === 'string') { + return func.apply(this, args); + } var rootNodeID = fnName === 'mountComponent' ? args[0] : @@ -12654,8 +13247,10 @@ var ReactDefaultPerf = { } entry.displayNames[rootNodeID] = { - current: this.constructor.displayName, - owner: this._owner ? this._owner.constructor.displayName : '<root>' + current: this.getName(), + owner: this._currentElement._owner ? + this._currentElement._owner.getName() : + '<root>' }; return rv; @@ -12668,9 +13263,9 @@ var ReactDefaultPerf = { module.exports = ReactDefaultPerf; -},{"./DOMProperty":53,"./ReactDefaultPerfAnalysis":98,"./ReactMount":111,"./ReactPerf":116,"./performanceNow":195}],98:[function(require,module,exports){ +},{"./DOMProperty":49,"./ReactDefaultPerfAnalysis":100,"./ReactMount":115,"./ReactPerf":120,"./performanceNow":201}],100:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12685,7 +13280,7 @@ var assign = require("./Object.assign"); // Don't try to save users less than 1.2ms (a number I made up) var DONT_CARE_THRESHOLD = 1.2; var DOM_OPERATION_TYPES = { - 'mountImageIntoNode': 'set innerHTML', + '_mountImageIntoNode': 'set innerHTML', INSERT_MARKUP: 'set innerHTML', MOVE_EXISTING: 'move', REMOVE_NODE: 'remove', @@ -12874,10 +13469,10 @@ var ReactDefaultPerfAnalysis = { module.exports = ReactDefaultPerfAnalysis; -},{"./Object.assign":70}],99:[function(require,module,exports){ +},{"./Object.assign":67}],101:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -12887,11 +13482,12 @@ module.exports = ReactDefaultPerfAnalysis; * @providesModule ReactElement */ -"use strict"; +'use strict'; var ReactContext = require("./ReactContext"); var ReactCurrentOwner = require("./ReactCurrentOwner"); +var assign = require("./Object.assign"); var warning = require("./warning"); var RESERVED_PROPS = { @@ -12922,8 +13518,9 @@ function defineWarningProperty(object, key) { set: function(value) { ("production" !== process.env.NODE_ENV ? warning( false, - 'Don\'t set the ' + key + ' property of the component. ' + - 'Mutate the existing props object instead.' + 'Don\'t set the %s property of the React element. Instead, ' + + 'specify the correct value when initially creating the element.', + key ) : null); this._store[key] = value; } @@ -12984,7 +13581,21 @@ var ReactElement = function(type, key, ref, owner, context, props) { // 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. - this._store = { validated: false, props: props }; + this._store = {props: props, originalProps: assign({}, props)}; + + // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + try { + Object.defineProperty(this._store, 'validated', { + configurable: false, + enumerable: false, + writable: true + }); + } catch (x) { + } + this._store.validated = false; // 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 @@ -13019,16 +13630,7 @@ ReactElement.createElement = function(type, config, children) { if (config != null) { ref = config.ref === undefined ? null : config.ref; - if ("production" !== process.env.NODE_ENV) { - ("production" !== process.env.NODE_ENV ? warning( - config.key !== null, - 'createElement(...): Encountered component with a `key` of null. In ' + - 'a future version, this will be treated as equivalent to the string ' + - '\'null\'; instead, provide an explicit key or use undefined.' - ) : null); - } - // TODO: Change this back to `config.key === undefined` - key = config.key == null ? null : '' + config.key; + key = config.key === undefined ? null : '' + config.key; // Remaining properties are added to a new props object for (propName in config) { if (config.hasOwnProperty(propName) && @@ -13052,7 +13654,7 @@ ReactElement.createElement = function(type, config, children) { } // Resolve default props - if (type.defaultProps) { + if (type && type.defaultProps) { var defaultProps = type.defaultProps; for (propName in defaultProps) { if (typeof props[propName] === 'undefined') { @@ -13077,6 +13679,7 @@ ReactElement.createFactory = function(type) { // easily accessed on elements. E.g. <Foo />.type === Foo.type. // This should not be named `constructor` since this may not be the function // that created the element, and it may not even be a constructor. + // Legacy hook TODO: Warn if this is accessed factory.type = type; return factory; }; @@ -13098,6 +13701,60 @@ ReactElement.cloneAndReplaceProps = function(oldElement, newProps) { return newElement; }; +ReactElement.cloneElement = function(element, config, children) { + var propName; + + // Original props are copied + var props = assign({}, element.props); + + // Reserved names are extracted + var key = element.key; + var ref = element.ref; + + // Owner will be preserved, unless ref is overridden + var owner = element._owner; + + if (config != null) { + if (config.ref !== undefined) { + // Silently steal the ref from the parent. + ref = config.ref; + owner = ReactCurrentOwner.current; + } + if (config.key !== undefined) { + key = '' + config.key; + } + // Remaining properties override existing props + for (propName in config) { + if (config.hasOwnProperty(propName) && + !RESERVED_PROPS.hasOwnProperty(propName)) { + props[propName] = config[propName]; + } + } + } + + // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. + var childrenLength = arguments.length - 2; + 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 + 2]; + } + props.children = childArray; + } + + return new ReactElement( + element.type, + key, + ref, + owner, + element._context, + props + ); +}; + /** * @param {?object} object * @return {boolean} True if `object` is a valid component. @@ -13120,9 +13777,10 @@ ReactElement.isValidElement = function(object) { module.exports = ReactElement; }).call(this,require('_process')) -},{"./ReactContext":82,"./ReactCurrentOwner":83,"./warning":202,"_process":1}],100:[function(require,module,exports){ +},{"./Object.assign":67,"./ReactContext":82,"./ReactCurrentOwner":83,"./warning":210,"_process":1}],102:[function(require,module,exports){ +(function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13139,30 +13797,59 @@ module.exports = ReactElement; * that support it. */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); +var ReactFragment = require("./ReactFragment"); var ReactPropTypeLocations = require("./ReactPropTypeLocations"); +var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames"); var ReactCurrentOwner = require("./ReactCurrentOwner"); +var ReactNativeComponent = require("./ReactNativeComponent"); + +var getIteratorFn = require("./getIteratorFn"); +var invariant = require("./invariant"); +var warning = require("./warning"); -var monitorCodeUse = require("./monitorCodeUse"); +function getDeclarationErrorAddendum() { + if (ReactCurrentOwner.current) { + var name = ReactCurrentOwner.current.getName(); + if (name) { + return ' Check the render method of `' + name + '`.'; + } + } + return ''; +} /** * 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 ownerHasKeyUseWarning = {}; var loggedTypeFailures = {}; var NUMERIC_PROPERTY_REGEX = /^\d+$/; /** + * Gets the instance's name for use in warnings. + * + * @internal + * @return {?string} Display name or undefined + */ +function getName(instance) { + var publicInstance = instance && instance.getPublicInstance(); + if (!publicInstance) { + return undefined; + } + var constructor = publicInstance.constructor; + if (!constructor) { + return undefined; + } + return constructor.displayName || constructor.name || undefined; +} + +/** * Gets the current owner's displayName for use in warnings. * * @internal @@ -13170,29 +13857,30 @@ var NUMERIC_PROPERTY_REGEX = /^\d+$/; */ function getCurrentOwnerDisplayName() { var current = ReactCurrentOwner.current; - return current && current.constructor.displayName || undefined; + return ( + current && getName(current) || 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 + * Warn if the element doesn't have an explicit key assigned to it. + * This element 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. + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. */ -function validateExplicitKey(component, parentType) { - if (component._store.validated || component.key != null) { +function validateExplicitKey(element, parentType) { + if (element._store.validated || element.key != null) { return; } - component._store.validated = true; + element._store.validated = true; warnAndMonitorForKeyUse( - 'react_key_warning', - 'Each child in an array should have a unique "key" prop.', - component, + 'Each child in an array or iterator should have a unique "key" prop.', + element, parentType ); } @@ -13203,17 +13891,16 @@ function validateExplicitKey(component, parentType) { * * @internal * @param {string} name Property name of the key. - * @param {ReactComponent} component Component that requires a key. - * @param {*} parentType component's parent's type. + * @param {ReactElement} element Component that requires a key. + * @param {*} parentType element's parent's type. */ -function validatePropertyKey(name, component, parentType) { +function validatePropertyKey(name, element, 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, + element, parentType ); } @@ -13222,85 +13909,90 @@ function validatePropertyKey(name, 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. + * @param {ReactElement} element Component that requires a key. + * @param {*} parentType element's parent's type. */ -function warnAndMonitorForKeyUse(warningID, message, component, parentType) { +function warnAndMonitorForKeyUse(message, element, parentType) { var ownerName = getCurrentOwnerDisplayName(); - var parentName = parentType.displayName; + var parentName = typeof parentType === 'string' ? + parentType : parentType.displayName || parentType.name; var useName = ownerName || parentName; - var memoizer = ownerHasKeyUseWarning[warningID]; + var memoizer = ownerHasKeyUseWarning[message] || ( + (ownerHasKeyUseWarning[message] = {}) + ); if (memoizer.hasOwnProperty(useName)) { return; } memoizer[useName] = true; - message += ownerName ? - (" Check the render method of " + ownerName + ".") : - (" Check the renderComponent call using <" + parentName + ">."); + var parentOrOwnerAddendum = + ownerName ? (" Check the render method of " + ownerName + ".") : + parentName ? (" Check the React.render 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) { + var childOwnerAddendum = ''; + if (element && + element._owner && + element._owner !== ReactCurrentOwner.current) { // Name of the component that originally created this child. - childOwnerName = component._owner.constructor.displayName; + var childOwnerName = getName(element._owner); - message += (" It was passed a child from " + childOwnerName + "."); + childOwnerAddendum = (" 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'); + ("production" !== process.env.NODE_ENV ? warning( + false, + message + '%s%s See http://fb.me/react-warning-keys for more information.', + parentOrOwnerAddendum, + childOwnerAddendum + ) : null); } /** - * Ensure that every component either is passed in a static location, in an + * Ensure that every element 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} + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. */ -function validateChildKeys(component, parentType) { - if (Array.isArray(component)) { - for (var i = 0; i < component.length; i++) { - var child = component[i]; +function validateChildKeys(node, parentType) { + if (Array.isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; if (ReactElement.isValidElement(child)) { validateExplicitKey(child, parentType); } } - } else if (ReactElement.isValidElement(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); + } else if (ReactElement.isValidElement(node)) { + // This element was passed in a valid location. + node._store.validated = true; + } else if (node) { + var iteratorFn = getIteratorFn(node); + // Entry iterators provide implicit keys. + if (iteratorFn) { + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + while (!(step = iterator.next()).done) { + if (ReactElement.isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } + } + } else if (typeof node === 'object') { + var fragment = ReactFragment.extractIfFragment(node); + for (var key in fragment) { + if (fragment.hasOwnProperty(key)) { + validatePropertyKey(key, fragment[key], parentType); + } + } } } } @@ -13322,6 +14014,16 @@ function checkPropTypes(componentName, propTypes, props, location) { // 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 { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + ("production" !== process.env.NODE_ENV ? invariant( + typeof propTypes[propName] === 'function', + '%s: %s type `%s` is invalid; it must be a function, usually from ' + + 'React.PropTypes.', + componentName || 'React class', + ReactPropTypeLocationNames[location], + propName + ) : invariant(typeof propTypes[propName] === 'function')); error = propTypes[propName](props, propName, componentName, location); } catch (ex) { error = ex; @@ -13330,19 +14032,148 @@ function checkPropTypes(componentName, propTypes, props, location) { // 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 addendum = getDeclarationErrorAddendum(this); + ("production" !== process.env.NODE_ENV ? warning(false, 'Failed propType: %s%s', error.message, addendum) : null); + } + } + } +} + +var warnedPropsMutations = {}; + +/** + * Warn about mutating props when setting `propName` on `element`. + * + * @param {string} propName The string key within props that was set + * @param {ReactElement} element + */ +function warnForPropsMutation(propName, element) { + var type = element.type; + var elementName = typeof type === 'string' ? type : type.displayName; + var ownerName = element._owner ? + element._owner.getPublicInstance().constructor.displayName : null; + + var warningKey = propName + '|' + elementName + '|' + ownerName; + if (warnedPropsMutations.hasOwnProperty(warningKey)) { + return; + } + warnedPropsMutations[warningKey] = true; + + var elementInfo = ''; + if (elementName) { + elementInfo = ' <' + elementName + ' />'; + } + var ownerInfo = ''; + if (ownerName) { + ownerInfo = ' The element was created by ' + ownerName + '.'; + } + + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Don\'t set .props.%s of the React component%s. ' + + 'Instead, specify the correct value when ' + + 'initially creating the element.%s', + propName, + elementInfo, + ownerInfo + ) : null); +} + +// Inline Object.is polyfill +function is(a, b) { + if (a !== a) { + // NaN + return b !== b; + } + if (a === 0 && b === 0) { + // +-0 + return 1 / a === 1 / b; + } + return a === b; +} + +/** + * Given an element, check if its props have been mutated since element + * creation (or the last call to this function). In particular, check if any + * new props have been added, which we can't directly catch by defining warning + * properties on the props object. + * + * @param {ReactElement} element + */ +function checkAndWarnForMutatedProps(element) { + if (!element._store) { + // Element was created using `new ReactElement` directly or with + // `ReactElement.createElement`; skip mutation checking + return; + } + + var originalProps = element._store.originalProps; + var props = element.props; + + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + if (!originalProps.hasOwnProperty(propName) || + !is(originalProps[propName], props[propName])) { + warnForPropsMutation(propName, element); + + // Copy over the new value so that the two props objects match again + originalProps[propName] = props[propName]; } } } } +/** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ +function validatePropTypes(element) { + if (element.type == null) { + // This has already warned. Don't throw. + return; + } + // Extract the component class from the element. Converts string types + // to a composite class which may have propTypes. + // TODO: Validating a string's propTypes is not decoupled from the + // rendering target which is problematic. + var componentClass = ReactNativeComponent.getComponentClassForElement( + element + ); + var name = componentClass.displayName || componentClass.name; + if (componentClass.propTypes) { + checkPropTypes( + name, + componentClass.propTypes, + element.props, + ReactPropTypeLocations.prop + ); + } + if (typeof componentClass.getDefaultProps === 'function') { + ("production" !== process.env.NODE_ENV ? warning( + componentClass.getDefaultProps.isReactClassApproved, + 'getDefaultProps is only used on classic React.createClass ' + + 'definitions. Use a static property named `defaultProps` instead.' + ) : null); + } +} + var ReactElementValidator = { + checkAndWarnForMutatedProps: checkAndWarnForMutatedProps, + createElement: function(type, props, children) { + // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + ("production" !== process.env.NODE_ENV ? warning( + type != null, + 'React.createElement: type should not be null or undefined. It should ' + + 'be a string (for DOM elements) or a ReactClass (for composite ' + + 'components).' + ) : null); + var element = ReactElement.createElement.apply(this, arguments); // The result can be nullish if a mock or a custom function is used. @@ -13355,23 +14186,8 @@ var ReactElementValidator = { validateChildKeys(arguments[i], type); } - var name = type.displayName; - if (type.propTypes) { - checkPropTypes( - name, - type.propTypes, - element.props, - ReactPropTypeLocations.prop - ); - } - if (type.contextTypes) { - checkPropTypes( - name, - type.contextTypes, - element._context, - ReactPropTypeLocations.context - ); - } + validatePropTypes(element); + return element; }, @@ -13380,18 +14196,56 @@ var ReactElementValidator = { null, type ); + // Legacy hook TODO: Warn if this is accessed validatedFactory.type = type; + + if ("production" !== process.env.NODE_ENV) { + try { + Object.defineProperty( + validatedFactory, + 'type', + { + enumerable: false, + get: function() { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'Factory.type is deprecated. Access the class directly ' + + 'before passing it to createFactory.' + ) : null); + Object.defineProperty(this, 'type', { + value: type + }); + return type; + } + } + ); + } catch (x) { + // IE will fail on defineProperty (es5-shim/sham too) + } + } + + return validatedFactory; + }, + + cloneElement: function(element, props, children) { + var newElement = ReactElement.cloneElement.apply(this, arguments); + for (var i = 2; i < arguments.length; i++) { + validateChildKeys(arguments[i], newElement.type); + } + validatePropTypes(newElement); + return newElement; } }; module.exports = ReactElementValidator; -},{"./ReactCurrentOwner":83,"./ReactElement":99,"./ReactPropTypeLocations":119,"./monitorCodeUse":192}],101:[function(require,module,exports){ +}).call(this,require('_process')) +},{"./ReactCurrentOwner":83,"./ReactElement":101,"./ReactFragment":107,"./ReactNativeComponent":118,"./ReactPropTypeLocationNames":122,"./ReactPropTypeLocations":123,"./getIteratorFn":180,"./invariant":189,"./warning":210,"_process":1}],103:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13401,16 +14255,17 @@ module.exports = ReactElementValidator; * @providesModule ReactEmptyComponent */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); +var ReactInstanceMap = require("./ReactInstanceMap"); var invariant = require("./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 nullComponentIDsRegistry = {}; var ReactEmptyComponentInjection = { injectEmptyComponent: function(emptyComponent) { @@ -13418,24 +14273,43 @@ var ReactEmptyComponentInjection = { } }; -/** - * @return {ReactComponent} component The injected empty component. - */ -function getEmptyComponent() { +var ReactEmptyComponentType = function() {}; +ReactEmptyComponentType.prototype.componentDidMount = function() { + var internalInstance = ReactInstanceMap.get(this); + // TODO: Make sure we run these methods in the correct order, we shouldn't + // need this check. We're going to assume if we're here it means we ran + // componentWillUnmount already so there is no internal instance (it gets + // removed as part of the unmounting process). + if (!internalInstance) { + return; + } + registerNullComponentID(internalInstance._rootNodeID); +}; +ReactEmptyComponentType.prototype.componentWillUnmount = function() { + var internalInstance = ReactInstanceMap.get(this); + // TODO: Get rid of this check. See TODO in componentDidMount. + if (!internalInstance) { + return; + } + deregisterNullComponentID(internalInstance._rootNodeID); +}; +ReactEmptyComponentType.prototype.render = function() { ("production" !== process.env.NODE_ENV ? invariant( component, 'Trying to return null from a render, but no null placeholder component ' + 'was injected.' ) : invariant(component)); return component(); -} +}; + +var emptyElement = ReactElement.createElement(ReactEmptyComponentType); /** * Mark the component as having rendered to null. * @param {string} id Component's `_rootNodeID`. */ function registerNullComponentID(id) { - nullComponentIdsRegistry[id] = true; + nullComponentIDsRegistry[id] = true; } /** @@ -13443,7 +14317,7 @@ function registerNullComponentID(id) { * @param {string} id Component's `_rootNodeID`. */ function deregisterNullComponentID(id) { - delete nullComponentIdsRegistry[id]; + delete nullComponentIDsRegistry[id]; } /** @@ -13451,23 +14325,21 @@ function deregisterNullComponentID(id) { * @return {boolean} True if the component is rendered to null. */ function isNullComponentID(id) { - return nullComponentIdsRegistry[id]; + return !!nullComponentIDsRegistry[id]; } var ReactEmptyComponent = { - deregisterNullComponentID: deregisterNullComponentID, - getEmptyComponent: getEmptyComponent, + emptyElement: emptyElement, injection: ReactEmptyComponentInjection, - isNullComponentID: isNullComponentID, - registerNullComponentID: registerNullComponentID + isNullComponentID: isNullComponentID }; module.exports = ReactEmptyComponent; }).call(this,require('_process')) -},{"./ReactElement":99,"./invariant":182,"_process":1}],102:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactInstanceMap":111,"./invariant":189,"_process":1}],104:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13497,9 +14369,9 @@ var ReactErrorUtils = { module.exports = ReactErrorUtils; -},{}],103:[function(require,module,exports){ +},{}],105:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13509,7 +14381,7 @@ module.exports = ReactErrorUtils; * @providesModule ReactEventEmitterMixin */ -"use strict"; +'use strict'; var EventPluginHub = require("./EventPluginHub"); @@ -13547,9 +14419,9 @@ var ReactEventEmitterMixin = { module.exports = ReactEventEmitterMixin; -},{"./EventPluginHub":60}],104:[function(require,module,exports){ +},{"./EventPluginHub":56}],106:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13560,7 +14432,7 @@ module.exports = ReactEventEmitterMixin; * @typechecks static-only */ -"use strict"; +'use strict'; var EventListener = require("./EventListener"); var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -13673,7 +14545,7 @@ var ReactEventListener = { trapBubbledEvent: function(topLevelType, handlerBaseName, handle) { var element = handle; if (!element) { - return; + return null; } return EventListener.listen( element, @@ -13695,7 +14567,7 @@ var ReactEventListener = { trapCapturedEvent: function(topLevelType, handlerBaseName, handle) { var element = handle; if (!element) { - return; + return null; } return EventListener.capture( element, @@ -13707,7 +14579,6 @@ var ReactEventListener = { monitorScrollValue: function(refresh) { var callback = scrollValueMonitor.bind(null, refresh); EventListener.listen(window, 'scroll', callback); - EventListener.listen(window, 'resize', callback); }, dispatchEvent: function(topLevelType, nativeEvent) { @@ -13731,9 +14602,194 @@ var ReactEventListener = { module.exports = ReactEventListener; -},{"./EventListener":59,"./ExecutionEnvironment":64,"./Object.assign":70,"./PooledClass":71,"./ReactInstanceHandles":107,"./ReactMount":111,"./ReactUpdates":132,"./getEventTarget":173,"./getUnboundedScrollPosition":178}],105:[function(require,module,exports){ +},{"./EventListener":55,"./ExecutionEnvironment":60,"./Object.assign":67,"./PooledClass":68,"./ReactInstanceHandles":110,"./ReactMount":115,"./ReactUpdates":138,"./getEventTarget":179,"./getUnboundedScrollPosition":185}],107:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * +* @providesModule ReactFragment +*/ + +'use strict'; + +var ReactElement = require("./ReactElement"); + +var warning = require("./warning"); + +/** + * We used to allow keyed objects to serve as a collection of ReactElements, + * or nested sets. This allowed us a way to explicitly key a set a fragment of + * components. This is now being replaced with an opaque data structure. + * The upgrade path is to call React.addons.createFragment({ key: value }) to + * create a keyed fragment. The resulting data structure is opaque, for now. + */ + +if ("production" !== process.env.NODE_ENV) { + var fragmentKey = '_reactFragment'; + var didWarnKey = '_reactDidWarn'; + var canWarnForReactFragment = false; + + try { + // Feature test. Don't even try to issue this warning if we can't use + // enumerable: false. + + var dummy = function() { + return 1; + }; + + Object.defineProperty( + {}, + fragmentKey, + {enumerable: false, value: true} + ); + + Object.defineProperty( + {}, + 'key', + {enumerable: true, get: dummy} + ); + + canWarnForReactFragment = true; + } catch (x) { } + + var proxyPropertyAccessWithWarning = function(obj, key) { + Object.defineProperty(obj, key, { + enumerable: true, + get: function() { + ("production" !== process.env.NODE_ENV ? warning( + this[didWarnKey], + 'A ReactFragment is an opaque type. Accessing any of its ' + + 'properties is deprecated. Pass it to one of the React.Children ' + + 'helpers.' + ) : null); + this[didWarnKey] = true; + return this[fragmentKey][key]; + }, + set: function(value) { + ("production" !== process.env.NODE_ENV ? warning( + this[didWarnKey], + 'A ReactFragment is an immutable opaque type. Mutating its ' + + 'properties is deprecated.' + ) : null); + this[didWarnKey] = true; + this[fragmentKey][key] = value; + } + }); + }; + + var issuedWarnings = {}; + + var didWarnForFragment = function(fragment) { + // We use the keys and the type of the value as a heuristic to dedupe the + // warning to avoid spamming too much. + var fragmentCacheKey = ''; + for (var key in fragment) { + fragmentCacheKey += key + ':' + (typeof fragment[key]) + ','; + } + var alreadyWarnedOnce = !!issuedWarnings[fragmentCacheKey]; + issuedWarnings[fragmentCacheKey] = true; + return alreadyWarnedOnce; + }; +} + +var ReactFragment = { + // Wrap a keyed object in an opaque proxy that warns you if you access any + // of its properties. + create: function(object) { + if ("production" !== process.env.NODE_ENV) { + if (typeof object !== 'object' || !object || Array.isArray(object)) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'React.addons.createFragment only accepts a single object.', + object + ) : null); + return object; + } + if (ReactElement.isValidElement(object)) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'React.addons.createFragment does not accept a ReactElement ' + + 'without a wrapper object.' + ) : null); + return object; + } + if (canWarnForReactFragment) { + var proxy = {}; + Object.defineProperty(proxy, fragmentKey, { + enumerable: false, + value: object + }); + Object.defineProperty(proxy, didWarnKey, { + writable: true, + enumerable: false, + value: false + }); + for (var key in object) { + proxyPropertyAccessWithWarning(proxy, key); + } + Object.preventExtensions(proxy); + return proxy; + } + } + return object; + }, + // Extract the original keyed object from the fragment opaque type. Warn if + // a plain object is passed here. + extract: function(fragment) { + if ("production" !== process.env.NODE_ENV) { + if (canWarnForReactFragment) { + if (!fragment[fragmentKey]) { + ("production" !== process.env.NODE_ENV ? warning( + didWarnForFragment(fragment), + 'Any use of a keyed object should be wrapped in ' + + 'React.addons.createFragment(object) before being passed as a ' + + 'child.' + ) : null); + return fragment; + } + return fragment[fragmentKey]; + } + } + return fragment; + }, + // Check if this is a fragment and if so, extract the keyed object. If it + // is a fragment-like object, warn that it should be wrapped. Ignore if we + // can't determine what kind of object this is. + extractIfFragment: function(fragment) { + if ("production" !== process.env.NODE_ENV) { + if (canWarnForReactFragment) { + // If it is the opaque type, return the keyed object. + if (fragment[fragmentKey]) { + return fragment[fragmentKey]; + } + // Otherwise, check each property if it has an element, if it does + // it is probably meant as a fragment, so we can warn early. Defer, + // the warning to extract. + for (var key in fragment) { + if (fragment.hasOwnProperty(key) && + ReactElement.isValidElement(fragment[key])) { + // This looks like a fragment object, we should provide an + // early warning. + return ReactFragment.extract(fragment); + } + } + } + } + return fragment; + } +}; + +module.exports = ReactFragment; + +}).call(this,require('_process')) +},{"./ReactElement":101,"./warning":210,"_process":1}],108:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13743,22 +14799,24 @@ module.exports = ReactEventListener; * @providesModule ReactInjection */ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); var EventPluginHub = require("./EventPluginHub"); -var ReactComponent = require("./ReactComponent"); -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactComponentEnvironment = require("./ReactComponentEnvironment"); +var ReactClass = require("./ReactClass"); var ReactEmptyComponent = require("./ReactEmptyComponent"); var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); var ReactNativeComponent = require("./ReactNativeComponent"); +var ReactDOMComponent = require("./ReactDOMComponent"); var ReactPerf = require("./ReactPerf"); var ReactRootIndex = require("./ReactRootIndex"); var ReactUpdates = require("./ReactUpdates"); var ReactInjection = { - Component: ReactComponent.injection, - CompositeComponent: ReactCompositeComponent.injection, + Component: ReactComponentEnvironment.injection, + Class: ReactClass.injection, + DOMComponent: ReactDOMComponent.injection, DOMProperty: DOMProperty.injection, EmptyComponent: ReactEmptyComponent.injection, EventPluginHub: EventPluginHub.injection, @@ -13771,9 +14829,9 @@ var ReactInjection = { module.exports = ReactInjection; -},{"./DOMProperty":53,"./EventPluginHub":60,"./ReactBrowserEventEmitter":74,"./ReactComponent":78,"./ReactCompositeComponent":81,"./ReactEmptyComponent":101,"./ReactNativeComponent":114,"./ReactPerf":116,"./ReactRootIndex":123,"./ReactUpdates":132}],106:[function(require,module,exports){ +},{"./DOMProperty":49,"./EventPluginHub":56,"./ReactBrowserEventEmitter":71,"./ReactClass":76,"./ReactComponentEnvironment":79,"./ReactDOMComponent":86,"./ReactEmptyComponent":103,"./ReactNativeComponent":118,"./ReactPerf":120,"./ReactRootIndex":129,"./ReactUpdates":138}],109:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13783,7 +14841,7 @@ module.exports = ReactInjection; * @providesModule ReactInputSelection */ -"use strict"; +'use strict'; var ReactDOMSelection = require("./ReactDOMSelection"); @@ -13805,9 +14863,8 @@ var ReactInputSelection = { hasSelectionCapabilities: function(elem) { return elem && ( - (elem.nodeName === 'INPUT' && elem.type === 'text') || - elem.nodeName === 'TEXTAREA' || - elem.contentEditable === 'true' + ((elem.nodeName === 'INPUT' && elem.type === 'text') || + elem.nodeName === 'TEXTAREA' || elem.contentEditable === 'true') ); }, @@ -13907,10 +14964,10 @@ var ReactInputSelection = { module.exports = ReactInputSelection; -},{"./ReactDOMSelection":93,"./containsNode":156,"./focusNode":167,"./getActiveElement":169}],107:[function(require,module,exports){ +},{"./ReactDOMSelection":94,"./containsNode":162,"./focusNode":173,"./getActiveElement":175}],110:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -13921,7 +14978,7 @@ module.exports = ReactInputSelection; * @typechecks static-only */ -"use strict"; +'use strict'; var ReactRootIndex = require("./ReactRootIndex"); @@ -14026,7 +15083,8 @@ function getNextDescendantID(ancestorID, destinationID) { // Skip over the ancestor and the immediate separator. Traverse until we hit // another separator or we reach the end of `destinationID`. var start = ancestorID.length + SEPARATOR_LENGTH; - for (var i = start; i < destinationID.length; i++) { + var i; + for (i = start; i < destinationID.length; i++) { if (isBoundary(destinationID, i)) { break; } @@ -14242,256 +15300,95 @@ var ReactInstanceHandles = { module.exports = ReactInstanceHandles; }).call(this,require('_process')) -},{"./ReactRootIndex":123,"./invariant":182,"_process":1}],108:[function(require,module,exports){ -(function (process){ +},{"./ReactRootIndex":129,"./invariant":189,"_process":1}],111:[function(require,module,exports){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule ReactLegacyElement + * @providesModule ReactInstanceMap */ -"use strict"; - -var ReactCurrentOwner = require("./ReactCurrentOwner"); - -var invariant = require("./invariant"); -var monitorCodeUse = require("./monitorCodeUse"); -var warning = require("./warning"); - -var legacyFactoryLogs = {}; -function warnForLegacyFactoryCall() { - if (!ReactLegacyElementFactory._isLegacyCallWarningEnabled) { - return; - } - var owner = ReactCurrentOwner.current; - var name = owner && owner.constructor ? owner.constructor.displayName : ''; - if (!name) { - name = 'Something'; - } - if (legacyFactoryLogs.hasOwnProperty(name)) { - return; - } - legacyFactoryLogs[name] = true; - ("production" !== process.env.NODE_ENV ? warning( - false, - name + ' is calling a React component directly. ' + - 'Use a factory or JSX instead. See: http://fb.me/react-legacyfactory' - ) : null); - monitorCodeUse('react_legacy_factory_call', { version: 3, name: name }); -} - -function warnForPlainFunctionType(type) { - var isReactClass = - type.prototype && - typeof type.prototype.mountComponent === 'function' && - typeof type.prototype.receiveComponent === 'function'; - if (isReactClass) { - ("production" !== process.env.NODE_ENV ? warning( - false, - 'Did not expect to get a React class here. Use `Component` instead ' + - 'of `Component.type` or `this.constructor`.' - ) : null); - } else { - if (!type._reactWarnedForThisType) { - try { - type._reactWarnedForThisType = true; - } catch (x) { - // just incase this is a frozen object or some special object - } - monitorCodeUse( - 'react_non_component_in_jsx', - { version: 3, name: type.name } - ); - } - ("production" !== process.env.NODE_ENV ? warning( - false, - 'This JSX uses a plain function. Only React components are ' + - 'valid in React\'s JSX transform.' - ) : null); - } -} - -function warnForNonLegacyFactory(type) { - ("production" !== process.env.NODE_ENV ? warning( - false, - 'Do not pass React.DOM.' + type.type + ' to JSX or createFactory. ' + - 'Use the string "' + type.type + '" instead.' - ) : null); -} +'use strict'; /** - * Transfer static properties from the source to the target. Functions are - * rebound to have this reflect the original source. + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. */ -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. - for (var k in value) { - if (value.hasOwnProperty(k)) { - bound[k] = value[k]; - } - } - target[key] = bound; - } else { - target[key] = value; - } - } - } -} -// We use an object instead of a boolean because booleans are ignored by our -// mocking libraries when these factories gets mocked. -var LEGACY_MARKER = {}; -var NON_LEGACY_MARKER = {}; +// TODO: Replace this with ES6: var ReactInstanceMap = new Map(); +var ReactInstanceMap = { -var ReactLegacyElementFactory = {}; - -ReactLegacyElementFactory.wrapCreateFactory = function(createFactory) { - var legacyCreateFactory = function(type) { - if (typeof type !== 'function') { - // Non-function types cannot be legacy factories - return createFactory(type); - } + /** + * This API should be called `delete` but we'd have to make sure to always + * transform these to strings for IE support. When this transform is fully + * supported we can rename it. + */ + remove: function(key) { + key._reactInternalInstance = undefined; + }, - if (type.isReactNonLegacyFactory) { - // This is probably a factory created by ReactDOM we unwrap it to get to - // the underlying string type. It shouldn't have been passed here so we - // warn. - if ("production" !== process.env.NODE_ENV) { - warnForNonLegacyFactory(type); - } - return createFactory(type.type); - } + get: function(key) { + return key._reactInternalInstance; + }, - if (type.isReactLegacyFactory) { - // This is probably a legacy factory created by ReactCompositeComponent. - // We unwrap it to get to the underlying class. - return createFactory(type.type); - } + has: function(key) { + return key._reactInternalInstance !== undefined; + }, - if ("production" !== process.env.NODE_ENV) { - warnForPlainFunctionType(type); - } + set: function(key, value) { + key._reactInternalInstance = value; + } - // Unless it's a legacy factory, then this is probably a plain function, - // that is expecting to be invoked by JSX. We can just return it as is. - return type; - }; - return legacyCreateFactory; }; -ReactLegacyElementFactory.wrapCreateElement = function(createElement) { - var legacyCreateElement = function(type, props, children) { - if (typeof type !== 'function') { - // Non-function types cannot be legacy factories - return createElement.apply(this, arguments); - } - - var args; +module.exports = ReactInstanceMap; - if (type.isReactNonLegacyFactory) { - // This is probably a factory created by ReactDOM we unwrap it to get to - // the underlying string type. It shouldn't have been passed here so we - // warn. - if ("production" !== process.env.NODE_ENV) { - warnForNonLegacyFactory(type); - } - args = Array.prototype.slice.call(arguments, 0); - args[0] = type.type; - return createElement.apply(this, args); - } - - if (type.isReactLegacyFactory) { - // This is probably a legacy factory created by ReactCompositeComponent. - // We unwrap it to get to the underlying class. - if (type._isMockFunction) { - // If this is a mock function, people will expect it to be called. We - // will actually call the original mock factory function instead. This - // future proofs unit testing that assume that these are classes. - type.type._mockedReactClassConstructor = type; - } - args = Array.prototype.slice.call(arguments, 0); - args[0] = type.type; - return createElement.apply(this, args); - } - - if ("production" !== process.env.NODE_ENV) { - warnForPlainFunctionType(type); - } - - // This is being called with a plain function we should invoke it - // immediately as if this was used with legacy JSX. - return type.apply(null, Array.prototype.slice.call(arguments, 1)); - }; - return legacyCreateElement; -}; - -ReactLegacyElementFactory.wrapFactory = function(factory) { - ("production" !== process.env.NODE_ENV ? invariant( - typeof factory === 'function', - 'This is suppose to accept a element factory' - ) : invariant(typeof factory === 'function')); - var legacyElementFactory = function(config, children) { - // This factory should not be called when JSX is used. Use JSX instead. - if ("production" !== process.env.NODE_ENV) { - warnForLegacyFactoryCall(); - } - return factory.apply(this, arguments); - }; - proxyStaticMethods(legacyElementFactory, factory.type); - legacyElementFactory.isReactLegacyFactory = LEGACY_MARKER; - legacyElementFactory.type = factory.type; - return legacyElementFactory; -}; +},{}],112:[function(require,module,exports){ +/** + * Copyright 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactLifeCycle + */ -// This is used to mark a factory that will remain. E.g. we're allowed to call -// it as a function. However, you're not suppose to pass it to createElement -// or createFactory, so it will warn you if you do. -ReactLegacyElementFactory.markNonLegacyFactory = function(factory) { - factory.isReactNonLegacyFactory = NON_LEGACY_MARKER; - return factory; -}; +'use strict'; -// Checks if a factory function is actually a legacy factory pretending to -// be a class. -ReactLegacyElementFactory.isValidFactory = function(factory) { - // TODO: This will be removed and moved into a class validator or something. - return typeof factory === 'function' && - factory.isReactLegacyFactory === LEGACY_MARKER; -}; +/** + * This module manages the bookkeeping when a component is in the process + * of being mounted or being unmounted. This is used as a way to enforce + * invariants (or warnings) when it is not recommended to call + * setState/forceUpdate. + * + * currentlyMountingInstance: During the construction phase, it is not possible + * to trigger an update since the instance is not fully mounted yet. However, we + * currently allow this as a convenience for mutating the initial state. + * + * currentlyUnmountingInstance: During the unmounting phase, the instance is + * still mounted and can therefore schedule an update. However, this is not + * recommended and probably an error since it's about to be unmounted. + * Therefore we still want to trigger in an error for that case. + */ -ReactLegacyElementFactory.isValidClass = function(factory) { - if ("production" !== process.env.NODE_ENV) { - ("production" !== process.env.NODE_ENV ? warning( - false, - 'isValidClass is deprecated and will be removed in a future release. ' + - 'Use a more specific validator instead.' - ) : null); - } - return ReactLegacyElementFactory.isValidFactory(factory); +var ReactLifeCycle = { + currentlyMountingInstance: null, + currentlyUnmountingInstance: null }; -ReactLegacyElementFactory._isLegacyCallWarningEnabled = true; - -module.exports = ReactLegacyElementFactory; +module.exports = ReactLifeCycle; -}).call(this,require('_process')) -},{"./ReactCurrentOwner":83,"./invariant":182,"./monitorCodeUse":192,"./warning":202,"_process":1}],109:[function(require,module,exports){ +},{}],113:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -14502,7 +15399,7 @@ module.exports = ReactLegacyElementFactory; * @typechecks static-only */ -"use strict"; +'use strict'; /** * ReactLink encapsulates a common pattern in which a component wants to modify @@ -14562,9 +15459,9 @@ ReactLink.PropTypes = { module.exports = ReactLink; -},{"./React":72}],110:[function(require,module,exports){ +},{"./React":69}],114:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -14574,7 +15471,7 @@ module.exports = ReactLink; * @providesModule ReactMarkupChecksum */ -"use strict"; +'use strict'; var adler32 = require("./adler32"); @@ -14610,10 +15507,10 @@ var ReactMarkupChecksum = { module.exports = ReactMarkupChecksum; -},{"./adler32":152}],111:[function(require,module,exports){ +},{"./adler32":158}],115:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -14623,28 +15520,31 @@ module.exports = ReactMarkupChecksum; * @providesModule ReactMount */ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactElement = require("./ReactElement"); -var ReactLegacyElement = require("./ReactLegacyElement"); +var ReactElementValidator = require("./ReactElementValidator"); +var ReactEmptyComponent = require("./ReactEmptyComponent"); var ReactInstanceHandles = require("./ReactInstanceHandles"); +var ReactInstanceMap = require("./ReactInstanceMap"); +var ReactMarkupChecksum = require("./ReactMarkupChecksum"); var ReactPerf = require("./ReactPerf"); +var ReactReconciler = require("./ReactReconciler"); +var ReactUpdateQueue = require("./ReactUpdateQueue"); +var ReactUpdates = require("./ReactUpdates"); +var emptyObject = require("./emptyObject"); var containsNode = require("./containsNode"); -var deprecated = require("./deprecated"); var getReactRootElementInContainer = require("./getReactRootElementInContainer"); var instantiateReactComponent = require("./instantiateReactComponent"); var invariant = require("./invariant"); +var setInnerHTML = require("./setInnerHTML"); var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); var warning = require("./warning"); -var createElement = ReactLegacyElement.wrapCreateElement( - ReactElement.createElement -); - var SEPARATOR = ReactInstanceHandles.SEPARATOR; var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; @@ -14668,6 +15568,22 @@ if ("production" !== process.env.NODE_ENV) { var findComponentRootReusableArray = []; /** + * Finds the index of the first character + * that's not common between the two given strings. + * + * @return {number} the index of the character where the strings diverge + */ +function firstDifferenceIndex(string1, string2) { + var minLen = Math.min(string1.length, string2.length); + for (var i = 0; i < minLen; i++) { + if (string1.charAt(i) !== string2.charAt(i)) { + return i; + } + } + return string1.length === string2.length ? -1 : minLen; +} + +/** * @param {DOMElement} container DOM element that may contain a React component. * @return {?string} A "reactRoot" ID, if a React component is rendered. */ @@ -14745,6 +15661,24 @@ function getNode(id) { } /** + * Finds the node with the supplied public React instance. + * + * @param {*} instance A public React instance. + * @return {?DOMElement} DOM node with the suppled `id`. + * @internal + */ +function getNodeFromInstance(instance) { + var id = ReactInstanceMap.get(instance)._rootNodeID; + if (ReactEmptyComponent.isNullComponentID(id)) { + return null; + } + if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) { + nodeCache[id] = ReactMount.findReactNodeByID(id); + } + return nodeCache[id]; +} + +/** * A node is "valid" if it is contained by a currently mounted container. * * This means that the node does not have to be contained by a document in @@ -14808,7 +15742,55 @@ function findDeepestCachedAncestor(targetID) { } /** - * Mounting is the process of initializing a React component by creatings its + * Mounts this component and inserts it into the DOM. + * + * @param {ReactComponent} componentInstance The instance to mount. + * @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 + */ +function mountComponentIntoNode( + componentInstance, + rootID, + container, + transaction, + shouldReuseMarkup) { + var markup = ReactReconciler.mountComponent( + componentInstance, rootID, transaction, emptyObject + ); + componentInstance._isTopLevel = true; + ReactMount._mountImageIntoNode(markup, container, shouldReuseMarkup); +} + +/** + * Batched mount. + * + * @param {ReactComponent} componentInstance The instance to mount. + * @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 + */ +function batchedMountComponentIntoNode( + componentInstance, + rootID, + container, + shouldReuseMarkup) { + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); + transaction.perform( + mountComponentIntoNode, + null, + componentInstance, + rootID, + container, + transaction, + shouldReuseMarkup + ); + ReactUpdates.ReactReconcileTransaction.release(transaction); +} + +/** + * Mounting is the process of initializing a React component by creating its * representative DOM elements and inserting them into a supplied `container`. * Any prior content inside `container` is destroyed in the process. * @@ -14844,18 +15826,24 @@ var ReactMount = { /** * Take a component that's already mounted into the DOM and replace its props * @param {ReactComponent} prevComponent component instance already in the DOM - * @param {ReactComponent} nextComponent component instance to render + * @param {ReactElement} nextElement component instance to render * @param {DOMElement} container container to render into * @param {?function} callback function triggered on completion */ _updateRootComponent: function( prevComponent, - nextComponent, + nextElement, container, callback) { - var nextProps = nextComponent.props; + if ("production" !== process.env.NODE_ENV) { + ReactElementValidator.checkAndWarnForMutatedProps(nextElement); + } + ReactMount.scrollMonitor(container, function() { - prevComponent.replaceProps(nextProps, callback); + ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement); + if (callback) { + ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback); + } }); if ("production" !== process.env.NODE_ENV) { @@ -14877,13 +15865,11 @@ var ReactMount = { _registerComponent: function(nextComponent, container) { ("production" !== process.env.NODE_ENV ? invariant( container && ( - container.nodeType === ELEMENT_NODE_TYPE || - container.nodeType === DOC_NODE_TYPE + (container.nodeType === ELEMENT_NODE_TYPE || 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 + (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE) ))); ReactBrowserEventEmitter.ensureScrollValueMonitoring(); @@ -14895,49 +15881,53 @@ var ReactMount = { /** * Render a new component into the DOM. - * @param {ReactComponent} nextComponent component instance to render + * @param {ReactElement} nextElement element to render * @param {DOMElement} container container to render into * @param {boolean} shouldReuseMarkup if we should skip the markup insertion * @return {ReactComponent} nextComponent */ - _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" !== process.env.NODE_ENV ? 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); + _renderNewRootComponent: function( + nextElement, + 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" !== process.env.NODE_ENV ? 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, null); - var reactRootID = ReactMount._registerComponent( - componentInstance, - container - ); - componentInstance.mountComponentIntoNode( - reactRootID, - container, - shouldReuseMarkup - ); + var componentInstance = instantiateReactComponent(nextElement, null); + var reactRootID = ReactMount._registerComponent( + componentInstance, + container + ); - if ("production" !== process.env.NODE_ENV) { - // Record the root element in case it later gets transplanted. - rootElementsByReactRootID[reactRootID] = - getReactRootElementInContainer(container); - } + // The initial render is synchronous but any updates that happen during + // rendering, in componentWillMount or componentDidMount, will be batched + // according to the current batching strategy. - return componentInstance; + ReactUpdates.batchedUpdates( + batchedMountComponentIntoNode, + componentInstance, + reactRootID, + container, + shouldReuseMarkup + ); + + if ("production" !== process.env.NODE_ENV) { + // Record the root element in case it later gets transplanted. + rootElementsByReactRootID[reactRootID] = + getReactRootElementInContainer(container); } - ), + + return componentInstance; + }, /** * Renders a React component into the DOM in the supplied `container`. @@ -14954,16 +15944,16 @@ var ReactMount = { render: function(nextElement, container, callback) { ("production" !== process.env.NODE_ENV ? invariant( ReactElement.isValidElement(nextElement), - 'renderComponent(): Invalid component element.%s', + 'React.render(): Invalid component element.%s', ( typeof nextElement === 'string' ? ' Instead of passing an element string, make sure to instantiate ' + 'it by passing it to React.createElement.' : - ReactLegacyElement.isValidFactory(nextElement) ? + typeof nextElement === 'function' ? ' Instead of passing a component class, make sure to instantiate ' + 'it by passing it to React.createElement.' : - // Check if it quacks like a element - typeof nextElement.props !== "undefined" ? + // Check if it quacks like an element + nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '' @@ -14980,7 +15970,7 @@ var ReactMount = { nextElement, container, callback - ); + ).getPublicInstance(); } else { ReactMount.unmountComponentAtNode(container); } @@ -14990,14 +15980,35 @@ var ReactMount = { var containerHasReactMarkup = reactRootElement && ReactMount.isRenderedByReact(reactRootElement); + if ("production" !== process.env.NODE_ENV) { + if (!containerHasReactMarkup || reactRootElement.nextSibling) { + var rootElementSibling = reactRootElement; + while (rootElementSibling) { + if (ReactMount.isRenderedByReact(rootElementSibling)) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'render(): Target node has markup rendered by React, but there ' + + 'are unrelated nodes as well. This is most commonly caused by ' + + 'white-space inserted around server-rendered markup.' + ) : null); + break; + } + + rootElementSibling = rootElementSibling.nextSibling; + } + } + } + var shouldReuseMarkup = containerHasReactMarkup && !prevComponent; var component = ReactMount._renderNewRootComponent( nextElement, container, shouldReuseMarkup - ); - callback && callback.call(component); + ).getPublicInstance(); + if (callback) { + callback.call(component); + } return component; }, @@ -15011,7 +16022,7 @@ var ReactMount = { * @return {ReactComponent} Component instance rendered in `container`. */ constructAndRenderComponent: function(constructor, props, container) { - var element = createElement(constructor, props); + var element = ReactElement.createElement(constructor, props); return ReactMount.render(element, container); }, @@ -15076,6 +16087,15 @@ var ReactMount = { 'componentDidUpdate.' ) : null); + ("production" !== process.env.NODE_ENV ? invariant( + container && ( + (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE) + ), + 'unmountComponentAtNode(...): Target container is not a DOM element.' + ) : invariant(container && ( + (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE) + ))); + var reactRootID = getReactRootID(container); var component = instancesByReactRootID[reactRootID]; if (!component) { @@ -15100,7 +16120,7 @@ var ReactMount = { * @see {ReactMount.unmountComponentAtNode} */ unmountComponentFromNode: function(instance, container) { - instance.unmountComponent(); + ReactReconciler.unmountComponent(instance); if (container.nodeType === DOC_NODE_TYPE) { container = container.documentElement; @@ -15144,10 +16164,11 @@ var ReactMount = { // warning is when the container is empty. rootElementsByReactRootID[reactRootID] = containerChild; } else { - console.warn( + ("production" !== process.env.NODE_ENV ? warning( + false, 'ReactMount: Root element has been removed from its original ' + 'container. New container:', rootElement.parentNode - ); + ) : null); } } } @@ -15280,6 +16301,77 @@ var ReactMount = { ) : invariant(false)); }, + _mountImageIntoNode: function(markup, container, shouldReuseMarkup) { + ("production" !== process.env.NODE_ENV ? invariant( + container && ( + (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE) + ), + 'mountComponentIntoNode(...): Target container is not valid.' + ) : invariant(container && ( + (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE) + ))); + + if (shouldReuseMarkup) { + var rootElement = getReactRootElementInContainer(container); + if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) { + return; + } else { + var checksum = rootElement.getAttribute( + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + ); + rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME); + + var rootMarkup = rootElement.outerHTML; + rootElement.setAttribute( + ReactMarkupChecksum.CHECKSUM_ATTR_NAME, + checksum + ); + + var diffIndex = firstDifferenceIndex(markup, rootMarkup); + var difference = ' (client) ' + + markup.substring(diffIndex - 20, diffIndex + 20) + + '\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20); + + ("production" !== process.env.NODE_ENV ? invariant( + container.nodeType !== DOC_NODE_TYPE, + 'You\'re trying to render a component to the document using ' + + 'server rendering but the checksum was invalid. This usually ' + + 'means you rendered a different component type or props on ' + + 'the client from the one on the server, or your render() ' + + 'methods are impure. React cannot handle this case due to ' + + 'cross-browser quirks by rendering at the document root. You ' + + 'should look for environment dependent code in your components ' + + 'and ensure the props are the same client and server side:\n%s', + difference + ) : invariant(container.nodeType !== DOC_NODE_TYPE)); + + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + false, + 'React attempted to 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 ' + + '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:\n%s', + difference + ) : null); + } + } + } + + ("production" !== process.env.NODE_ENV ? 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 React.renderToString() for server rendering.' + ) : invariant(container.nodeType !== DOC_NODE_TYPE)); + + setInnerHTML(container, markup); + }, /** * React ID utilities. @@ -15293,24 +16385,22 @@ var ReactMount = { getNode: getNode, + getNodeFromInstance: getNodeFromInstance, + purgeID: purgeID }; -// Deprecations (remove for 0.13) -ReactMount.renderComponent = deprecated( - 'ReactMount', - 'renderComponent', - 'render', - this, - ReactMount.render -); +ReactPerf.measureMethods(ReactMount, 'ReactMount', { + _renderNewRootComponent: '_renderNewRootComponent', + _mountImageIntoNode: '_mountImageIntoNode' +}); module.exports = ReactMount; }).call(this,require('_process')) -},{"./DOMProperty":53,"./ReactBrowserEventEmitter":74,"./ReactCurrentOwner":83,"./ReactElement":99,"./ReactInstanceHandles":107,"./ReactLegacyElement":108,"./ReactPerf":116,"./containsNode":156,"./deprecated":162,"./getReactRootElementInContainer":176,"./instantiateReactComponent":181,"./invariant":182,"./shouldUpdateReactComponent":198,"./warning":202,"_process":1}],112:[function(require,module,exports){ +},{"./DOMProperty":49,"./ReactBrowserEventEmitter":71,"./ReactCurrentOwner":83,"./ReactElement":101,"./ReactElementValidator":102,"./ReactEmptyComponent":103,"./ReactInstanceHandles":110,"./ReactInstanceMap":111,"./ReactMarkupChecksum":114,"./ReactPerf":120,"./ReactReconciler":127,"./ReactUpdateQueue":137,"./ReactUpdates":138,"./containsNode":162,"./emptyObject":169,"./getReactRootElementInContainer":183,"./instantiateReactComponent":188,"./invariant":189,"./setInnerHTML":203,"./shouldUpdateReactComponent":206,"./warning":210,"_process":1}],116:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -15321,14 +16411,13 @@ module.exports = ReactMount; * @typechecks static-only */ -"use strict"; +'use strict'; -var ReactComponent = require("./ReactComponent"); +var ReactComponentEnvironment = require("./ReactComponentEnvironment"); var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); -var flattenChildren = require("./flattenChildren"); -var instantiateReactComponent = require("./instantiateReactComponent"); -var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); +var ReactReconciler = require("./ReactReconciler"); +var ReactChildReconciler = require("./ReactChildReconciler"); /** * Updating children of a component may trigger recursive updates. The depth is @@ -15446,7 +16535,7 @@ function enqueueTextContent(parentID, textContent) { */ function processQueue() { if (updateQueue.length) { - ReactComponent.BackendIDOperations.dangerouslyProcessChildrenUpdates( + ReactComponentEnvironment.processChildrenUpdates( updateQueue, markupQueue ); @@ -15489,26 +16578,25 @@ var ReactMultiChild = { * @return {array} An array of mounted representations. * @internal */ - mountChildren: function(nestedChildren, transaction) { - var children = flattenChildren(nestedChildren); + mountChildren: function(nestedChildren, transaction, context) { + var children = ReactChildReconciler.instantiateChildren( + nestedChildren, transaction, context + ); + this._renderedChildren = children; var mountImages = []; var index = 0; - this._renderedChildren = children; for (var name in children) { - var child = children[name]; if (children.hasOwnProperty(name)) { - // The rendered children must be turned into instances as they're - // mounted. - var childInstance = instantiateReactComponent(child, null); - children[name] = childInstance; + var child = children[name]; // Inlined for performance, see `ReactInstanceHandles.createReactID`. var rootID = this._rootNodeID + name; - var mountImage = childInstance.mountComponent( + var mountImage = ReactReconciler.mountComponent( + child, rootID, transaction, - this._mountDepth + 1 + context ); - childInstance._mountIndex = index; + child._mountIndex = index; mountImages.push(mountImage); index++; } @@ -15528,6 +16616,8 @@ var ReactMultiChild = { try { var prevChildren = this._renderedChildren; // Remove any rendered children. + ReactChildReconciler.unmountChildren(prevChildren); + // TODO: The setTextContent operation should be enough for (var name in prevChildren) { if (prevChildren.hasOwnProperty(name)) { this._unmountChildByName(prevChildren[name], name); @@ -15539,7 +16629,11 @@ var ReactMultiChild = { } finally { updateDepth--; if (!updateDepth) { - errorThrown ? clearQueue() : processQueue(); + if (errorThrown) { + clearQueue(); + } else { + processQueue(); + } } } }, @@ -15551,17 +16645,22 @@ var ReactMultiChild = { * @param {ReactReconcileTransaction} transaction * @internal */ - updateChildren: function(nextNestedChildren, transaction) { + updateChildren: function(nextNestedChildren, transaction, context) { updateDepth++; var errorThrown = true; try { - this._updateChildren(nextNestedChildren, transaction); + this._updateChildren(nextNestedChildren, transaction, context); errorThrown = false; } finally { updateDepth--; if (!updateDepth) { - errorThrown ? clearQueue() : processQueue(); + if (errorThrown) { + clearQueue(); + } else { + processQueue(); + } } + } }, @@ -15574,9 +16673,12 @@ var ReactMultiChild = { * @final * @protected */ - _updateChildren: function(nextNestedChildren, transaction) { - var nextChildren = flattenChildren(nextNestedChildren); + _updateChildren: function(nextNestedChildren, transaction, context) { var prevChildren = this._renderedChildren; + var nextChildren = ReactChildReconciler.updateChildren( + prevChildren, nextNestedChildren, transaction, context + ); + this._renderedChildren = nextChildren; if (!nextChildren && !prevChildren) { return; } @@ -15590,12 +16692,10 @@ var ReactMultiChild = { continue; } var prevChild = prevChildren && prevChildren[name]; - var prevElement = prevChild && prevChild._currentElement; - var nextElement = nextChildren[name]; - if (shouldUpdateReactComponent(prevElement, nextElement)) { + var nextChild = nextChildren[name]; + if (prevChild === nextChild) { this.moveChild(prevChild, nextIndex, lastIndex); lastIndex = Math.max(prevChild._mountIndex, lastIndex); - prevChild.receiveComponent(nextElement, transaction); prevChild._mountIndex = nextIndex; } else { if (prevChild) { @@ -15604,12 +16704,8 @@ var ReactMultiChild = { this._unmountChildByName(prevChild, name); } // The child must be instantiated before it's mounted. - var nextChildInstance = instantiateReactComponent( - nextElement, - null - ); this._mountChildByNameAtIndex( - nextChildInstance, name, nextIndex, transaction + nextChild, name, nextIndex, transaction, context ); } nextIndex++; @@ -15617,7 +16713,7 @@ var ReactMultiChild = { // Remove children that are no longer present. for (name in prevChildren) { if (prevChildren.hasOwnProperty(name) && - !(nextChildren && nextChildren[name])) { + !(nextChildren && nextChildren.hasOwnProperty(name))) { this._unmountChildByName(prevChildren[name], name); } } @@ -15631,13 +16727,7 @@ var ReactMultiChild = { */ unmountChildren: function() { var renderedChildren = this._renderedChildren; - for (var name in renderedChildren) { - var renderedChild = renderedChildren[name]; - // TODO: When is this not true? - if (renderedChild.unmountComponent) { - renderedChild.unmountComponent(); - } - } + ReactChildReconciler.unmountChildren(renderedChildren); this._renderedChildren = null; }, @@ -15700,18 +16790,22 @@ var ReactMultiChild = { * @param {ReactReconcileTransaction} transaction * @private */ - _mountChildByNameAtIndex: function(child, name, index, transaction) { + _mountChildByNameAtIndex: function( + child, + name, + index, + transaction, + context) { // Inlined for performance, see `ReactInstanceHandles.createReactID`. var rootID = this._rootNodeID + name; - var mountImage = child.mountComponent( + var mountImage = ReactReconciler.mountComponent( + child, rootID, transaction, - this._mountDepth + 1 + context ); child._mountIndex = index; this.createChild(child, mountImage); - this._renderedChildren = this._renderedChildren || {}; - this._renderedChildren[name] = child; }, /** @@ -15726,8 +16820,6 @@ var ReactMultiChild = { _unmountChildByName: function(child, name) { this.removeChild(child); child._mountIndex = null; - child.unmountComponent(); - delete this._renderedChildren[name]; } } @@ -15736,9 +16828,9 @@ var ReactMultiChild = { module.exports = ReactMultiChild; -},{"./ReactComponent":78,"./ReactMultiChildUpdateTypes":113,"./flattenChildren":166,"./instantiateReactComponent":181,"./shouldUpdateReactComponent":198}],113:[function(require,module,exports){ +},{"./ReactChildReconciler":74,"./ReactComponentEnvironment":79,"./ReactMultiChildUpdateTypes":117,"./ReactReconciler":127}],117:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -15748,7 +16840,7 @@ module.exports = ReactMultiChild; * @providesModule ReactMultiChildUpdateTypes */ -"use strict"; +'use strict'; var keyMirror = require("./keyMirror"); @@ -15769,10 +16861,10 @@ var ReactMultiChildUpdateTypes = keyMirror({ module.exports = ReactMultiChildUpdateTypes; -},{"./keyMirror":188}],114:[function(require,module,exports){ +},{"./keyMirror":195}],118:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -15782,14 +16874,16 @@ module.exports = ReactMultiChildUpdateTypes; * @providesModule ReactNativeComponent */ -"use strict"; +'use strict'; var assign = require("./Object.assign"); var invariant = require("./invariant"); +var autoGenerateWrapperClass = null; var genericComponentClass = null; // This registry keeps track of wrapper classes around native tags var tagToComponentClass = {}; +var textComponentClass = null; var ReactNativeComponentInjection = { // This accepts a class that receives the tag string. This is a catch all @@ -15797,55 +16891,87 @@ var ReactNativeComponentInjection = { injectGenericComponentClass: function(componentClass) { genericComponentClass = componentClass; }, + // This accepts a text component class that takes the text string to be + // rendered as props. + injectTextComponentClass: function(componentClass) { + textComponentClass = componentClass; + }, // This accepts a keyed object with classes as values. Each key represents a // tag. That particular tag will use this class instead of the generic one. injectComponentClasses: function(componentClasses) { assign(tagToComponentClass, componentClasses); + }, + // Temporary hack since we expect DOM refs to behave like composites, + // for this release. + injectAutoWrapper: function(wrapperFactory) { + autoGenerateWrapperClass = wrapperFactory; } }; /** - * Create an internal class for a specific tag. + * Get a composite component wrapper class for a specific tag. * - * @param {string} tag The tag for which to create an internal instance. - * @param {any} props The props passed to the instance constructor. - * @return {ReactComponent} component The injected empty component. + * @param {ReactElement} element The tag for which to get the class. + * @return {function} The React class constructor function. */ -function createInstanceForTag(tag, props, parentType) { +function getComponentClassForElement(element) { + if (typeof element.type === 'function') { + return element.type; + } + var tag = element.type; var componentClass = tagToComponentClass[tag]; if (componentClass == null) { - ("production" !== process.env.NODE_ENV ? invariant( - genericComponentClass, - 'There is no registered component for the tag %s', - tag - ) : invariant(genericComponentClass)); - return new genericComponentClass(tag, props); - } - if (parentType === tag) { - // Avoid recursion - ("production" !== process.env.NODE_ENV ? invariant( - genericComponentClass, - 'There is no registered component for the tag %s', - tag - ) : invariant(genericComponentClass)); - return new genericComponentClass(tag, props); + tagToComponentClass[tag] = componentClass = autoGenerateWrapperClass(tag); } - // Unwrap legacy factories - return new componentClass.type(props); + return componentClass; +} + +/** + * Get a native internal component class for a specific tag. + * + * @param {ReactElement} element The element to create. + * @return {function} The internal class constructor function. + */ +function createInternalComponent(element) { + ("production" !== process.env.NODE_ENV ? invariant( + genericComponentClass, + 'There is no registered component for the tag %s', + element.type + ) : invariant(genericComponentClass)); + return new genericComponentClass(element.type, element.props); +} + +/** + * @param {ReactText} text + * @return {ReactComponent} + */ +function createInstanceForText(text) { + return new textComponentClass(text); +} + +/** + * @param {ReactComponent} component + * @return {boolean} + */ +function isTextComponent(component) { + return component instanceof textComponentClass; } var ReactNativeComponent = { - createInstanceForTag: createInstanceForTag, - injection: ReactNativeComponentInjection, + getComponentClassForElement: getComponentClassForElement, + createInternalComponent: createInternalComponent, + createInstanceForText: createInstanceForText, + isTextComponent: isTextComponent, + injection: ReactNativeComponentInjection }; module.exports = ReactNativeComponent; }).call(this,require('_process')) -},{"./Object.assign":70,"./invariant":182,"_process":1}],115:[function(require,module,exports){ +},{"./Object.assign":67,"./invariant":189,"_process":1}],119:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -15855,9 +16981,8 @@ module.exports = ReactNativeComponent; * @providesModule ReactOwner */ -"use strict"; +'use strict'; -var emptyObject = require("./emptyObject"); var invariant = require("./invariant"); /** @@ -15899,9 +17024,8 @@ var ReactOwner = { */ isValidOwner: function(object) { return !!( - object && - typeof object.attachRef === 'function' && - typeof object.detachRef === 'function' + (object && + typeof object.attachRef === 'function' && typeof object.detachRef === 'function') ); }, @@ -15946,51 +17070,9 @@ var ReactOwner = { ) : invariant(ReactOwner.isValidOwner(owner))); // Check that `component` is still the current ref because we do not want to // detach the ref if another component stole it. - if (owner.refs[ref] === component) { + if (owner.getPublicInstance().refs[ref] === component.getPublicInstance()) { owner.detachRef(ref); } - }, - - /** - * A ReactComponent must mix this in to have refs. - * - * @lends {ReactOwner.prototype} - */ - Mixin: { - - construct: function() { - this.refs = emptyObject; - }, - - /** - * Lazily allocates the refs object and stores `component` as `ref`. - * - * @param {string} ref Reference name. - * @param {component} component Component to store as `ref`. - * @final - * @private - */ - attachRef: function(ref, component) { - ("production" !== process.env.NODE_ENV ? invariant( - component.isOwnedBy(this), - 'attachRef(%s, ...): Only a component\'s owner can store a ref to it.', - ref - ) : invariant(component.isOwnedBy(this))); - var refs = this.refs === emptyObject ? (this.refs = {}) : this.refs; - refs[ref] = component; - }, - - /** - * Detaches a reference name. - * - * @param {string} ref Name to dereference. - * @final - * @private - */ - detachRef: function(ref) { - delete this.refs[ref]; - } - } }; @@ -15998,10 +17080,10 @@ var ReactOwner = { module.exports = ReactOwner; }).call(this,require('_process')) -},{"./emptyObject":164,"./invariant":182,"_process":1}],116:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],120:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16012,7 +17094,7 @@ module.exports = ReactOwner; * @typechecks static-only */ -"use strict"; +'use strict'; /** * ReactPerf is a general AOP system designed to measure performance. This @@ -16032,6 +17114,26 @@ var ReactPerf = { storedMeasure: _noMeasure, /** + * @param {object} object + * @param {string} objectName + * @param {object<string>} methodNames + */ + measureMethods: function(object, objectName, methodNames) { + if ("production" !== process.env.NODE_ENV) { + for (var key in methodNames) { + if (!methodNames.hasOwnProperty(key)) { + continue; + } + object[key] = ReactPerf.measure( + objectName, + methodNames[key], + object[key] + ); + } + } + }, + + /** * Use this to wrap methods you want to measure. Zero overhead in production. * * @param {string} objName @@ -16082,10 +17184,9 @@ function _noMeasure(objName, fnName, func) { module.exports = ReactPerf; }).call(this,require('_process')) -},{"_process":1}],117:[function(require,module,exports){ -(function (process){ +},{"_process":1}],121:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16095,15 +17196,11 @@ module.exports = ReactPerf; * @providesModule ReactPropTransferer */ -"use strict"; +'use strict'; var assign = require("./Object.assign"); var emptyFunction = require("./emptyFunction"); -var invariant = require("./invariant"); var joinClasses = require("./joinClasses"); -var warning = require("./warning"); - -var didWarn = false; /** * Creates a transfer strategy that will merge prop values using the supplied @@ -16182,8 +17279,6 @@ function transferInto(props, newProps) { */ var ReactPropTransferer = { - TransferStrategies: TransferStrategies, - /** * Merge two props objects using TransferStrategies. * @@ -16193,66 +17288,16 @@ var ReactPropTransferer = { */ mergeProps: function(oldProps, newProps) { return transferInto(assign({}, oldProps), newProps); - }, - - /** - * @lends {ReactPropTransferer.prototype} - */ - Mixin: { - - /** - * Transfer props from this component to a target component. - * - * Props that do not have an explicit transfer strategy will be transferred - * only if the target component does not already have the prop set. - * - * This is usually used to pass down props to a returned root component. - * - * @param {ReactElement} element Component receiving the properties. - * @return {ReactElement} The supplied `component`. - * @final - * @protected - */ - transferPropsTo: function(element) { - ("production" !== process.env.NODE_ENV ? invariant( - element._owner === this, - '%s: You can\'t call transferPropsTo() on a component that you ' + - 'don\'t own, %s. This usually means you are calling ' + - 'transferPropsTo() on a component passed in as props or children.', - this.constructor.displayName, - typeof element.type === 'string' ? - element.type : - element.type.displayName - ) : invariant(element._owner === this)); - - if ("production" !== process.env.NODE_ENV) { - if (!didWarn) { - didWarn = true; - ("production" !== process.env.NODE_ENV ? warning( - false, - 'transferPropsTo is deprecated. ' + - 'See http://fb.me/react-transferpropsto for more information.' - ) : null); - } - } - - // Because elements are immutable we have to merge into the existing - // props object rather than clone it. - transferInto(element.props, this.props); - - return element; - } - } + }; module.exports = ReactPropTransferer; -}).call(this,require('_process')) -},{"./Object.assign":70,"./emptyFunction":163,"./invariant":182,"./joinClasses":187,"./warning":202,"_process":1}],118:[function(require,module,exports){ +},{"./Object.assign":67,"./emptyFunction":168,"./joinClasses":194}],122:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16262,7 +17307,7 @@ module.exports = ReactPropTransferer; * @providesModule ReactPropTypeLocationNames */ -"use strict"; +'use strict'; var ReactPropTypeLocationNames = {}; @@ -16277,9 +17322,9 @@ if ("production" !== process.env.NODE_ENV) { module.exports = ReactPropTypeLocationNames; }).call(this,require('_process')) -},{"_process":1}],119:[function(require,module,exports){ +},{"_process":1}],123:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16289,7 +17334,7 @@ module.exports = ReactPropTypeLocationNames; * @providesModule ReactPropTypeLocations */ -"use strict"; +'use strict'; var keyMirror = require("./keyMirror"); @@ -16301,9 +17346,9 @@ var ReactPropTypeLocations = keyMirror({ module.exports = ReactPropTypeLocations; -},{"./keyMirror":188}],120:[function(require,module,exports){ +},{"./keyMirror":195}],124:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16313,12 +17358,12 @@ module.exports = ReactPropTypeLocations; * @providesModule ReactPropTypes */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); +var ReactFragment = require("./ReactFragment"); var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames"); -var deprecated = require("./deprecated"); var emptyFunction = require("./emptyFunction"); /** @@ -16389,22 +17434,7 @@ var ReactPropTypes = { objectOf: createObjectOfTypeChecker, oneOf: createEnumTypeChecker, oneOfType: createUnionTypeChecker, - shape: createShapeTypeChecker, - - component: deprecated( - 'React.PropTypes', - 'component', - 'element', - this, - elementTypeChecker - ), - renderable: deprecated( - 'React.PropTypes', - 'renderable', - 'node', - this, - nodeTypeChecker - ) + shape: createShapeTypeChecker }; function createChainableTypeChecker(validate) { @@ -16414,10 +17444,11 @@ function createChainableTypeChecker(validate) { var locationName = ReactPropTypeLocationNames[location]; if (isRequired) { return new Error( - ("Required " + locationName + " `" + propName + "` was not specified in ")+ + ("Required " + locationName + " `" + propName + "` was not specified in ") + ("`" + componentName + "`.") ); } + return null; } else { return validate(props, propName, componentName, location); } @@ -16445,12 +17476,13 @@ function createPrimitiveTypeChecker(expectedType) { ("supplied to `" + componentName + "`, expected `" + expectedType + "`.") ); } + return null; } return createChainableTypeChecker(validate); } function createAnyTypeChecker() { - return createChainableTypeChecker(emptyFunction.thatReturns()); + return createChainableTypeChecker(emptyFunction.thatReturns(null)); } function createArrayOfTypeChecker(typeChecker) { @@ -16470,6 +17502,7 @@ function createArrayOfTypeChecker(typeChecker) { return error; } } + return null; } return createChainableTypeChecker(validate); } @@ -16483,6 +17516,7 @@ function createElementTypeChecker() { ("`" + componentName + "`, expected a ReactElement.") ); } + return null; } return createChainableTypeChecker(validate); } @@ -16497,6 +17531,7 @@ function createInstanceTypeChecker(expectedClass) { ("`" + componentName + "`, expected instance of `" + expectedClassName + "`.") ); } + return null; } return createChainableTypeChecker(validate); } @@ -16506,7 +17541,7 @@ function createEnumTypeChecker(expectedValues) { var propValue = props[propName]; for (var i = 0; i < expectedValues.length; i++) { if (propValue === expectedValues[i]) { - return; + return null; } } @@ -16539,6 +17574,7 @@ function createObjectOfTypeChecker(typeChecker) { } } } + return null; } return createChainableTypeChecker(validate); } @@ -16548,7 +17584,7 @@ function createUnionTypeChecker(arrayOfTypeCheckers) { for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (checker(props, propName, componentName, location) == null) { - return; + return null; } } @@ -16570,6 +17606,7 @@ function createNodeChecker() { ("`" + componentName + "`, expected a ReactNode.") ); } + return null; } return createChainableTypeChecker(validate); } @@ -16595,14 +17632,16 @@ function createShapeTypeChecker(shapeTypes) { return error; } } + return null; } - return createChainableTypeChecker(validate, 'expected `object`'); + return createChainableTypeChecker(validate); } function isNode(propValue) { - switch(typeof propValue) { + switch (typeof propValue) { case 'number': case 'string': + case 'undefined': return true; case 'boolean': return !propValue; @@ -16610,9 +17649,10 @@ function isNode(propValue) { if (Array.isArray(propValue)) { return propValue.every(isNode); } - if (ReactElement.isValidElement(propValue)) { + if (propValue === null || ReactElement.isValidElement(propValue)) { return true; } + propValue = ReactFragment.extractIfFragment(propValue); for (var k in propValue) { if (!isNode(propValue[k])) { return false; @@ -16655,9 +17695,9 @@ function getPreciseType(propValue) { module.exports = ReactPropTypes; -},{"./ReactElement":99,"./ReactPropTypeLocationNames":118,"./deprecated":162,"./emptyFunction":163}],121:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactFragment":107,"./ReactPropTypeLocationNames":122,"./emptyFunction":168}],125:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16667,7 +17707,7 @@ module.exports = ReactPropTypes; * @providesModule ReactPutListenerQueue */ -"use strict"; +'use strict'; var PooledClass = require("./PooledClass"); var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); @@ -16711,9 +17751,9 @@ PooledClass.addPoolingTo(ReactPutListenerQueue); module.exports = ReactPutListenerQueue; -},{"./Object.assign":70,"./PooledClass":71,"./ReactBrowserEventEmitter":74}],122:[function(require,module,exports){ +},{"./Object.assign":67,"./PooledClass":68,"./ReactBrowserEventEmitter":71}],126:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16724,7 +17764,7 @@ module.exports = ReactPutListenerQueue; * @typechecks static-only */ -"use strict"; +'use strict'; var CallbackQueue = require("./CallbackQueue"); var PooledClass = require("./PooledClass"); @@ -16887,9 +17927,204 @@ PooledClass.addPoolingTo(ReactReconcileTransaction); module.exports = ReactReconcileTransaction; -},{"./CallbackQueue":48,"./Object.assign":70,"./PooledClass":71,"./ReactBrowserEventEmitter":74,"./ReactInputSelection":106,"./ReactPutListenerQueue":121,"./Transaction":149}],123:[function(require,module,exports){ +},{"./CallbackQueue":45,"./Object.assign":67,"./PooledClass":68,"./ReactBrowserEventEmitter":71,"./ReactInputSelection":109,"./ReactPutListenerQueue":125,"./Transaction":155}],127:[function(require,module,exports){ +(function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactReconciler + */ + +'use strict'; + +var ReactRef = require("./ReactRef"); +var ReactElementValidator = require("./ReactElementValidator"); + +/** + * Helper to call ReactRef.attachRefs with this composite component, split out + * to avoid allocations in the transaction mount-ready queue. + */ +function attachRefs() { + ReactRef.attachRefs(this, this._currentElement); +} + +var ReactReconciler = { + + /** + * Initializes the component, renders markup, and registers event listeners. + * + * @param {ReactComponent} internalInstance + * @param {string} rootID DOM ID of the root node. + * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction + * @return {?string} Rendered markup to be inserted into the DOM. + * @final + * @internal + */ + mountComponent: function(internalInstance, rootID, transaction, context) { + var markup = internalInstance.mountComponent(rootID, transaction, context); + if ("production" !== process.env.NODE_ENV) { + ReactElementValidator.checkAndWarnForMutatedProps( + internalInstance._currentElement + ); + } + transaction.getReactMountReady().enqueue(attachRefs, internalInstance); + return markup; + }, + + /** + * Releases any resources allocated by `mountComponent`. + * + * @final + * @internal + */ + unmountComponent: function(internalInstance) { + ReactRef.detachRefs(internalInstance, internalInstance._currentElement); + internalInstance.unmountComponent(); + }, + + /** + * Update a component using a new element. + * + * @param {ReactComponent} internalInstance + * @param {ReactElement} nextElement + * @param {ReactReconcileTransaction} transaction + * @param {object} context + * @internal + */ + receiveComponent: function( + internalInstance, nextElement, transaction, context + ) { + var prevElement = internalInstance._currentElement; + + if (nextElement === prevElement && nextElement._owner != null) { + // Since elements 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 element. We explicitly check for the existence of an owner since + // it's possible for an element created outside a composite to be + // deeply mutated and reused. + return; + } + + if ("production" !== process.env.NODE_ENV) { + ReactElementValidator.checkAndWarnForMutatedProps(nextElement); + } + + var refsChanged = ReactRef.shouldUpdateRefs( + prevElement, + nextElement + ); + + if (refsChanged) { + ReactRef.detachRefs(internalInstance, prevElement); + } + + internalInstance.receiveComponent(nextElement, transaction, context); + + if (refsChanged) { + transaction.getReactMountReady().enqueue(attachRefs, internalInstance); + } + }, + + /** + * Flush any dirty changes in a component. + * + * @param {ReactComponent} internalInstance + * @param {ReactReconcileTransaction} transaction + * @internal + */ + performUpdateIfNecessary: function( + internalInstance, + transaction + ) { + internalInstance.performUpdateIfNecessary(transaction); + } + +}; + +module.exports = ReactReconciler; + +}).call(this,require('_process')) +},{"./ReactElementValidator":102,"./ReactRef":128,"_process":1}],128:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactRef + */ + +'use strict'; + +var ReactOwner = require("./ReactOwner"); + +var ReactRef = {}; + +function attachRef(ref, component, owner) { + if (typeof ref === 'function') { + ref(component.getPublicInstance()); + } else { + // Legacy ref + ReactOwner.addComponentAsRefTo(component, ref, owner); + } +} + +function detachRef(ref, component, owner) { + if (typeof ref === 'function') { + ref(null); + } else { + // Legacy ref + ReactOwner.removeComponentAsRefFrom(component, ref, owner); + } +} + +ReactRef.attachRefs = function(instance, element) { + var ref = element.ref; + if (ref != null) { + attachRef(ref, instance, element._owner); + } +}; + +ReactRef.shouldUpdateRefs = function(prevElement, nextElement) { + // 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`. We use the element instead + // of the public this.props because the post processing cannot determine + // a ref. The ref conceptually lives on the element. + + // 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. + + return ( + nextElement._owner !== prevElement._owner || + nextElement.ref !== prevElement.ref + ); +}; + +ReactRef.detachRefs = function(instance, element) { + var ref = element.ref; + if (ref != null) { + detachRef(ref, instance, element._owner); + } +}; + +module.exports = ReactRef; + +},{"./ReactOwner":119}],129:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16900,7 +18135,7 @@ module.exports = ReactReconcileTransaction; * @typechecks */ -"use strict"; +'use strict'; var ReactRootIndexInjection = { /** @@ -16918,10 +18153,10 @@ var ReactRootIndex = { module.exports = ReactRootIndex; -},{}],124:[function(require,module,exports){ +},{}],130:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -16931,7 +18166,7 @@ module.exports = ReactRootIndex; * @typechecks static-only * @providesModule ReactServerRendering */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); var ReactInstanceHandles = require("./ReactInstanceHandles"); @@ -16939,6 +18174,7 @@ var ReactMarkupChecksum = require("./ReactMarkupChecksum"); var ReactServerRenderingTransaction = require("./ReactServerRenderingTransaction"); +var emptyObject = require("./emptyObject"); var instantiateReactComponent = require("./instantiateReactComponent"); var invariant = require("./invariant"); @@ -16959,7 +18195,8 @@ function renderToString(element) { return transaction.perform(function() { var componentInstance = instantiateReactComponent(element, null); - var markup = componentInstance.mountComponent(id, transaction, 0); + var markup = + componentInstance.mountComponent(id, transaction, emptyObject); return ReactMarkupChecksum.addChecksumToMarkup(markup); }, null); } finally { @@ -16985,7 +18222,7 @@ function renderToStaticMarkup(element) { return transaction.perform(function() { var componentInstance = instantiateReactComponent(element, null); - return componentInstance.mountComponent(id, transaction, 0); + return componentInstance.mountComponent(id, transaction, emptyObject); }, null); } finally { ReactServerRenderingTransaction.release(transaction); @@ -16998,9 +18235,9 @@ module.exports = { }; }).call(this,require('_process')) -},{"./ReactElement":99,"./ReactInstanceHandles":107,"./ReactMarkupChecksum":110,"./ReactServerRenderingTransaction":125,"./instantiateReactComponent":181,"./invariant":182,"_process":1}],125:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactInstanceHandles":110,"./ReactMarkupChecksum":114,"./ReactServerRenderingTransaction":131,"./emptyObject":169,"./instantiateReactComponent":188,"./invariant":189,"_process":1}],131:[function(require,module,exports){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17011,7 +18248,7 @@ module.exports = { * @typechecks */ -"use strict"; +'use strict'; var PooledClass = require("./PooledClass"); var CallbackQueue = require("./CallbackQueue"); @@ -17111,9 +18348,9 @@ PooledClass.addPoolingTo(ReactServerRenderingTransaction); module.exports = ReactServerRenderingTransaction; -},{"./CallbackQueue":48,"./Object.assign":70,"./PooledClass":71,"./ReactPutListenerQueue":121,"./Transaction":149,"./emptyFunction":163}],126:[function(require,module,exports){ +},{"./CallbackQueue":45,"./Object.assign":67,"./PooledClass":68,"./ReactPutListenerQueue":125,"./Transaction":155,"./emptyFunction":168}],132:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17123,7 +18360,7 @@ module.exports = ReactServerRenderingTransaction; * @providesModule ReactStateSetters */ -"use strict"; +'use strict'; var ReactStateSetters = { /** @@ -17217,9 +18454,9 @@ ReactStateSetters.Mixin = { module.exports = ReactStateSetters; -},{}],127:[function(require,module,exports){ +},{}],133:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17229,16 +18466,19 @@ module.exports = ReactStateSetters; * @providesModule ReactTestUtils */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPluginHub = require("./EventPluginHub"); var EventPropagators = require("./EventPropagators"); var React = require("./React"); var ReactElement = require("./ReactElement"); +var ReactEmptyComponent = require("./ReactEmptyComponent"); var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter"); +var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactInstanceHandles = require("./ReactInstanceHandles"); +var ReactInstanceMap = require("./ReactInstanceMap"); var ReactMount = require("./ReactMount"); -var ReactTextComponent = require("./ReactTextComponent"); var ReactUpdates = require("./ReactUpdates"); var SyntheticEvent = require("./SyntheticEvent"); @@ -17275,12 +18515,14 @@ var ReactTestUtils = { isElementOfType: function(inst, convenienceConstructor) { return ( ReactElement.isValidElement(inst) && - inst.type === convenienceConstructor.type + inst.type === convenienceConstructor ); }, isDOMComponent: function(inst) { - return !!(inst && inst.mountComponent && inst.tagName); + // TODO: Fix this heuristic. It's just here because composites can currently + // pretend to be DOM components. + return !!(inst && inst.tagName && inst.getDOMNode); }, isDOMComponentElement: function(inst) { @@ -17296,7 +18538,7 @@ var ReactTestUtils = { isCompositeComponentWithType: function(inst, type) { return !!(ReactTestUtils.isCompositeComponent(inst) && - (inst.constructor === type.type)); + (inst.constructor === type)); }, isCompositeComponentElement: function(inst) { @@ -17317,8 +18559,12 @@ var ReactTestUtils = { (inst.constructor === type)); }, - isTextComponent: function(inst) { - return inst instanceof ReactTextComponent.type; + getRenderedChildOfCompositeComponent: function(inst) { + if (!ReactTestUtils.isCompositeComponent(inst)) { + return null; + } + var internalInstance = ReactInstanceMap.get(inst); + return internalInstance._renderedComponent.getPublicInstance(); }, findAllInRenderedTree: function(inst, test) { @@ -17327,19 +18573,31 @@ var ReactTestUtils = { } var ret = test(inst) ? [inst] : []; if (ReactTestUtils.isDOMComponent(inst)) { - var renderedChildren = inst._renderedChildren; + var internalInstance = ReactInstanceMap.get(inst); + var renderedChildren = internalInstance + ._renderedComponent + ._renderedChildren; var key; for (key in renderedChildren) { if (!renderedChildren.hasOwnProperty(key)) { continue; } + if (!renderedChildren[key].getPublicInstance) { + continue; + } ret = ret.concat( - ReactTestUtils.findAllInRenderedTree(renderedChildren[key], test) + ReactTestUtils.findAllInRenderedTree( + renderedChildren[key].getPublicInstance(), + test + ) ); } } else if (ReactTestUtils.isCompositeComponent(inst)) { ret = ret.concat( - ReactTestUtils.findAllInRenderedTree(inst._renderedComponent, test) + ReactTestUtils.findAllInRenderedTree( + ReactTestUtils.getRenderedChildOfCompositeComponent(inst), + test + ) ); } return ret; @@ -17354,8 +18612,7 @@ var ReactTestUtils = { return ReactTestUtils.findAllInRenderedTree(root, function(inst) { var instClassName = inst.props.className; return ReactTestUtils.isDOMComponent(inst) && ( - instClassName && - (' ' + instClassName + ' ').indexOf(' ' + className + ' ') !== -1 + (instClassName && (' ' + instClassName + ' ').indexOf(' ' + className + ' ') !== -1) ); }); }, @@ -17370,7 +18627,9 @@ var ReactTestUtils = { var all = ReactTestUtils.scryRenderedDOMComponentsWithClass(root, className); if (all.length !== 1) { - throw new Error('Did not find exactly one match for class:' + className); + throw new Error('Did not find exactly one match ' + + '(found: ' + all.length + ') for class:' + className + ); } return all[0]; }, @@ -17451,21 +18710,14 @@ var ReactTestUtils = { mockComponent: function(module, mockTagName) { mockTagName = mockTagName || module.mockTagName || "div"; - var ConvenienceConstructor = React.createClass({displayName: 'ConvenienceConstructor', - render: function() { - return React.createElement( - mockTagName, - null, - this.props.children - ); - } + module.prototype.render.mockImplementation(function() { + return React.createElement( + mockTagName, + null, + this.props.children + ); }); - module.mockImplementation(ConvenienceConstructor); - - module.type = ConvenienceConstructor.type; - module.isReactLegacyFactory = true; - return this; }, @@ -17510,11 +18762,94 @@ var ReactTestUtils = { }; }, + createRenderer: function() { + return new ReactShallowRenderer(); + }, + Simulate: null, SimulateNative: {} }; /** + * @class ReactShallowRenderer + */ +var ReactShallowRenderer = function() { + this._instance = null; +}; + +ReactShallowRenderer.prototype.getRenderOutput = function() { + return ( + (this._instance && this._instance._renderedComponent && + this._instance._renderedComponent._renderedOutput) + || null + ); +}; + +var NoopInternalComponent = function(element) { + this._renderedOutput = element; + this._currentElement = element === null || element === false ? + ReactEmptyComponent.emptyElement : + element; +}; + +NoopInternalComponent.prototype = { + + mountComponent: function() { + }, + + receiveComponent: function(element) { + this._renderedOutput = element; + this._currentElement = element === null || element === false ? + ReactEmptyComponent.emptyElement : + element; + }, + + unmountComponent: function() { + } + +}; + +var ShallowComponentWrapper = function() { }; +assign( + ShallowComponentWrapper.prototype, + ReactCompositeComponent.Mixin, { + _instantiateReactComponent: function(element) { + return new NoopInternalComponent(element); + }, + _replaceNodeWithMarkupByID: function() {}, + _renderValidatedComponent: + ReactCompositeComponent.Mixin. + _renderValidatedComponentWithoutOwnerOrContext + } +); + +ReactShallowRenderer.prototype.render = function(element, context) { + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); + this._render(element, transaction, context); + ReactUpdates.ReactReconcileTransaction.release(transaction); +}; + +ReactShallowRenderer.prototype.unmount = function() { + if (this._instance) { + this._instance.unmountComponent(); + } +}; + +ReactShallowRenderer.prototype._render = function(element, transaction, context) { + if (!this._instance) { + var rootID = ReactInstanceHandles.createReactRootID(); + var instance = new ShallowComponentWrapper(element.type); + instance.construct(element); + + instance.mountComponent(rootID, transaction, context); + + this._instance = instance; + } else { + this._instance.receiveComponent(element, transaction, context); + } +}; + +/** * Exports: * * - `ReactTestUtils.Simulate.click(Element/ReactDOMComponent)` @@ -17629,115 +18964,9 @@ for (eventType in topLevelTypes) { module.exports = ReactTestUtils; -},{"./EventConstants":58,"./EventPluginHub":60,"./EventPropagators":63,"./Object.assign":70,"./React":72,"./ReactBrowserEventEmitter":74,"./ReactElement":99,"./ReactMount":111,"./ReactTextComponent":128,"./ReactUpdates":132,"./SyntheticEvent":141}],128:[function(require,module,exports){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ReactTextComponent - * @typechecks static-only - */ - -"use strict"; - -var DOMPropertyOperations = require("./DOMPropertyOperations"); -var ReactComponent = require("./ReactComponent"); -var ReactElement = require("./ReactElement"); - -var assign = require("./Object.assign"); -var escapeTextForBrowser = require("./escapeTextForBrowser"); - -/** - * Text nodes violate a couple assumptions that React makes about components: - * - * - When mounting text into the DOM, adjacent text nodes are merged. - * - Text nodes cannot be assigned a React root ID. - * - * This component is used to wrap strings in elements so that they can undergo - * the same reconciliation that is applied to elements. - * - * TODO: Investigate representing React components in the DOM with text nodes. - * - * @class ReactTextComponent - * @extends ReactComponent - * @internal - */ -var ReactTextComponent = function(props) { - // This constructor and it's argument is currently used by mocks. -}; - -assign(ReactTextComponent.prototype, ReactComponent.Mixin, { - - /** - * Creates the markup for this text node. This node is not intended to have - * any features besides containing text content. - * - * @param {string} rootID DOM ID of the root node. - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy - * @return {string} Markup for this text node. - * @internal - */ - mountComponent: function(rootID, transaction, mountDepth) { - ReactComponent.Mixin.mountComponent.call( - this, - rootID, - transaction, - mountDepth - ); - - var escapedText = escapeTextForBrowser(this.props); - - if (transaction.renderToStaticMarkup) { - // Normally we'd wrap this in a `span` for the reasons stated above, but - // since this is a situation where React won't take over (static pages), - // we can simply return the text as it is. - return escapedText; - } - - return ( - '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' + - escapedText + - '</span>' - ); - }, - - /** - * Updates this component by updating the text content. - * - * @param {object} nextComponent Contains the next text content. - * @param {ReactReconcileTransaction} transaction - * @internal - */ - receiveComponent: function(nextComponent, transaction) { - var nextProps = nextComponent.props; - if (nextProps !== this.props) { - this.props = nextProps; - ReactComponent.BackendIDOperations.updateTextContentByID( - this._rootNodeID, - nextProps - ); - } - } - -}); - -var ReactTextComponentFactory = function(text) { - // Bypass validation and configuration - return new ReactElement(ReactTextComponent, null, null, null, null, text); -}; - -ReactTextComponentFactory.type = ReactTextComponent; - -module.exports = ReactTextComponentFactory; - -},{"./DOMPropertyOperations":54,"./Object.assign":70,"./ReactComponent":78,"./ReactElement":99,"./escapeTextForBrowser":165}],129:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPluginHub":56,"./EventPropagators":59,"./Object.assign":67,"./React":69,"./ReactBrowserEventEmitter":71,"./ReactCompositeComponent":81,"./ReactElement":101,"./ReactEmptyComponent":103,"./ReactInstanceHandles":110,"./ReactInstanceMap":111,"./ReactMount":115,"./ReactUpdates":138,"./SyntheticEvent":147}],134:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17748,9 +18977,10 @@ module.exports = ReactTextComponentFactory; * @providesModule ReactTransitionChildMapping */ -"use strict"; +'use strict'; var ReactChildren = require("./ReactChildren"); +var ReactFragment = require("./ReactFragment"); var ReactTransitionChildMapping = { /** @@ -17761,9 +18991,12 @@ var ReactTransitionChildMapping = { * @return {object} Mapping of key to child */ getChildMapping: function(children) { - return ReactChildren.map(children, function(child) { + if (!children) { + return children; + } + return ReactFragment.extract(ReactChildren.map(children, function(child) { return child; - }); + })); }, /** @@ -17836,9 +19069,9 @@ var ReactTransitionChildMapping = { module.exports = ReactTransitionChildMapping; -},{"./ReactChildren":77}],130:[function(require,module,exports){ +},{"./ReactChildren":75,"./ReactFragment":107}],135:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17848,7 +19081,7 @@ module.exports = ReactTransitionChildMapping; * @providesModule ReactTransitionEvents */ -"use strict"; +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -17947,9 +19180,9 @@ var ReactTransitionEvents = { module.exports = ReactTransitionEvents; -},{"./ExecutionEnvironment":64}],131:[function(require,module,exports){ +},{"./ExecutionEnvironment":60}],136:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -17959,7 +19192,7 @@ module.exports = ReactTransitionEvents; * @providesModule ReactTransitionGroup */ -"use strict"; +'use strict'; var React = require("./React"); var ReactTransitionChildMapping = require("./ReactTransitionChildMapping"); @@ -17989,6 +19222,21 @@ var ReactTransitionGroup = React.createClass({ }; }, + componentWillMount: function() { + this.currentlyTransitioningKeys = {}; + this.keysToEnter = []; + this.keysToLeave = []; + }, + + componentDidMount: function() { + var initialChildMapping = this.state.children; + for (var key in initialChildMapping) { + if (initialChildMapping[key]) { + this.performAppear(key); + } + } + }, + componentWillReceiveProps: function(nextProps) { var nextChildMapping = ReactTransitionChildMapping.getChildMapping( nextProps.children @@ -18023,12 +19271,6 @@ var ReactTransitionGroup = React.createClass({ // If we want to someday check for reordering, we could do it here. }, - componentWillMount: function() { - this.currentlyTransitioningKeys = {}; - this.keysToEnter = []; - this.keysToLeave = []; - }, - componentDidUpdate: function() { var keysToEnter = this.keysToEnter; this.keysToEnter = []; @@ -18039,6 +19281,38 @@ var ReactTransitionGroup = React.createClass({ keysToLeave.forEach(this.performLeave); }, + performAppear: function(key) { + this.currentlyTransitioningKeys[key] = true; + + var component = this.refs[key]; + + if (component.componentWillAppear) { + component.componentWillAppear( + this._handleDoneAppearing.bind(this, key) + ); + } else { + this._handleDoneAppearing(key); + } + }, + + _handleDoneAppearing: function(key) { + var component = this.refs[key]; + if (component.componentDidAppear) { + component.componentDidAppear(); + } + + delete this.currentlyTransitioningKeys[key]; + + var currentChildMapping = ReactTransitionChildMapping.getChildMapping( + this.props.children + ); + + if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) { + // This was removed before it had fully appeared. Remove it. + this.performLeave(key); + } + }, + performEnter: function(key) { this.currentlyTransitioningKeys[key] = true; @@ -18111,7 +19385,7 @@ var ReactTransitionGroup = React.createClass({ render: function() { // TODO: we could get rid of the need for the wrapper node // by cloning a single child - var childrenToRender = {}; + var childrenToRender = []; for (var key in this.state.children) { var child = this.state.children[key]; if (child) { @@ -18120,10 +19394,10 @@ var ReactTransitionGroup = React.createClass({ // already been removed. In case you need this behavior you can provide // a childFactory function to wrap every child, even the ones that are // leaving. - childrenToRender[key] = cloneWithProps( + childrenToRender.push(cloneWithProps( this.props.childFactory(child), - {ref: key} - ); + {ref: key, key: key} + )); } } return React.createElement( @@ -18136,10 +19410,309 @@ var ReactTransitionGroup = React.createClass({ module.exports = ReactTransitionGroup; -},{"./Object.assign":70,"./React":72,"./ReactTransitionChildMapping":129,"./cloneWithProps":155,"./emptyFunction":163}],132:[function(require,module,exports){ +},{"./Object.assign":67,"./React":69,"./ReactTransitionChildMapping":134,"./cloneWithProps":161,"./emptyFunction":168}],137:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactUpdateQueue + */ + +'use strict'; + +var ReactLifeCycle = require("./ReactLifeCycle"); +var ReactCurrentOwner = require("./ReactCurrentOwner"); +var ReactElement = require("./ReactElement"); +var ReactInstanceMap = require("./ReactInstanceMap"); +var ReactUpdates = require("./ReactUpdates"); + +var assign = require("./Object.assign"); +var invariant = require("./invariant"); +var warning = require("./warning"); + +function enqueueUpdate(internalInstance) { + if (internalInstance !== ReactLifeCycle.currentlyMountingInstance) { + // 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. + // See bug in #1740. + ReactUpdates.enqueueUpdate(internalInstance); + } +} + +function getInternalInstanceReadyForUpdate(publicInstance, callerName) { + ("production" !== process.env.NODE_ENV ? invariant( + ReactCurrentOwner.current == null, + '%s(...): Cannot update during an existing state transition ' + + '(such as within `render`). Render methods should be a pure function ' + + 'of props and state.', + callerName + ) : invariant(ReactCurrentOwner.current == null)); + + var internalInstance = ReactInstanceMap.get(publicInstance); + if (!internalInstance) { + if ("production" !== process.env.NODE_ENV) { + // Only warn when we have a callerName. Otherwise we should be silent. + // We're probably calling from enqueueCallback. We don't want to warn + // there because we already warned for the corresponding lifecycle method. + ("production" !== process.env.NODE_ENV ? warning( + !callerName, + '%s(...): Can only update a mounted or mounting component. ' + + 'This usually means you called %s() on an unmounted ' + + 'component. This is a no-op.', + callerName, + callerName + ) : null); + } + return null; + } + + if (internalInstance === ReactLifeCycle.currentlyUnmountingInstance) { + return null; + } + + return internalInstance; +} + +/** + * ReactUpdateQueue allows for state updates to be scheduled into a later + * reconciliation step. + */ +var ReactUpdateQueue = { + + /** + * Enqueue a callback that will be executed after all the pending updates + * have processed. + * + * @param {ReactClass} publicInstance The instance to use as `this` context. + * @param {?function} callback Called after state is updated. + * @internal + */ + enqueueCallback: function(publicInstance, callback) { + ("production" !== process.env.NODE_ENV ? invariant( + typeof callback === 'function', + 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' + + '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + + 'isn\'t callable.' + ) : invariant(typeof callback === 'function')); + var internalInstance = getInternalInstanceReadyForUpdate(publicInstance); + + // Previously we would throw an error if we didn't have an internal + // instance. Since we want to make it a no-op instead, we mirror the same + // behavior we have in other enqueue* methods. + // We also need to ignore callbacks in componentWillMount. See + // enqueueUpdates. + if (!internalInstance || + internalInstance === ReactLifeCycle.currentlyMountingInstance) { + return null; + } + + if (internalInstance._pendingCallbacks) { + internalInstance._pendingCallbacks.push(callback); + } else { + internalInstance._pendingCallbacks = [callback]; + } + // TODO: The callback here is ignored when setState is called from + // componentWillMount. Either fix it or disallow doing so completely in + // favor of getInitialState. Alternatively, we can disallow + // componentWillMount during server-side rendering. + enqueueUpdate(internalInstance); + }, + + enqueueCallbackInternal: function(internalInstance, callback) { + ("production" !== process.env.NODE_ENV ? invariant( + typeof callback === 'function', + 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' + + '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + + 'isn\'t callable.' + ) : invariant(typeof callback === 'function')); + if (internalInstance._pendingCallbacks) { + internalInstance._pendingCallbacks.push(callback); + } else { + internalInstance._pendingCallbacks = [callback]; + } + enqueueUpdate(internalInstance); + }, + + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldUpdateComponent`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @internal + */ + enqueueForceUpdate: function(publicInstance) { + var internalInstance = getInternalInstanceReadyForUpdate( + publicInstance, + 'forceUpdate' + ); + + if (!internalInstance) { + return; + } + + internalInstance._pendingForceUpdate = true; + + enqueueUpdate(internalInstance); + }, + + /** + * Replaces all of the state. Always use this or `setState` to mutate state. + * You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} completeState Next state. + * @internal + */ + enqueueReplaceState: function(publicInstance, completeState) { + var internalInstance = getInternalInstanceReadyForUpdate( + publicInstance, + 'replaceState' + ); + + if (!internalInstance) { + return; + } + + internalInstance._pendingStateQueue = [completeState]; + internalInstance._pendingReplaceState = true; + + enqueueUpdate(internalInstance); + }, + + /** + * Sets a subset of the state. This only exists because _pendingState is + * internal. This provides a merging strategy that is not available to deep + * properties which is confusing. TODO: Expose pendingState or don't use it + * during the merge. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} partialState Next partial state to be merged with state. + * @internal + */ + enqueueSetState: function(publicInstance, partialState) { + var internalInstance = getInternalInstanceReadyForUpdate( + publicInstance, + 'setState' + ); + + if (!internalInstance) { + return; + } + + var queue = + internalInstance._pendingStateQueue || + (internalInstance._pendingStateQueue = []); + queue.push(partialState); + + enqueueUpdate(internalInstance); + }, + + /** + * Sets a subset of the props. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} partialProps Subset of the next props. + * @internal + */ + enqueueSetProps: function(publicInstance, partialProps) { + var internalInstance = getInternalInstanceReadyForUpdate( + publicInstance, + 'setProps' + ); + + if (!internalInstance) { + return; + } + + ("production" !== process.env.NODE_ENV ? invariant( + internalInstance._isTopLevel, + 'setProps(...): You called `setProps` 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(internalInstance._isTopLevel)); + + // Merge with the pending element if it exists, otherwise with existing + // element props. + var element = internalInstance._pendingElement || + internalInstance._currentElement; + var props = assign({}, element.props, partialProps); + internalInstance._pendingElement = ReactElement.cloneAndReplaceProps( + element, + props + ); + + enqueueUpdate(internalInstance); + }, + + /** + * Replaces all of the props. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} props New props. + * @internal + */ + enqueueReplaceProps: function(publicInstance, props) { + var internalInstance = getInternalInstanceReadyForUpdate( + publicInstance, + 'replaceProps' + ); + + if (!internalInstance) { + return; + } + + ("production" !== process.env.NODE_ENV ? invariant( + internalInstance._isTopLevel, + 'replaceProps(...): You called `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(internalInstance._isTopLevel)); + + // Merge with the pending element if it exists, otherwise with existing + // element props. + var element = internalInstance._pendingElement || + internalInstance._currentElement; + internalInstance._pendingElement = ReactElement.cloneAndReplaceProps( + element, + props + ); + + enqueueUpdate(internalInstance); + }, + + enqueueElementInternal: function(internalInstance, newElement) { + internalInstance._pendingElement = newElement; + enqueueUpdate(internalInstance); + } + +}; + +module.exports = ReactUpdateQueue; + +}).call(this,require('_process')) +},{"./Object.assign":67,"./ReactCurrentOwner":83,"./ReactElement":101,"./ReactInstanceMap":111,"./ReactLifeCycle":112,"./ReactUpdates":138,"./invariant":189,"./warning":210,"_process":1}],138:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18149,12 +19722,13 @@ module.exports = ReactTransitionGroup; * @providesModule ReactUpdates */ -"use strict"; +'use strict'; var CallbackQueue = require("./CallbackQueue"); var PooledClass = require("./PooledClass"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactPerf = require("./ReactPerf"); +var ReactReconciler = require("./ReactReconciler"); var Transaction = require("./Transaction"); var assign = require("./Object.assign"); @@ -18244,20 +19818,20 @@ assign( PooledClass.addPoolingTo(ReactUpdatesFlushTransaction); -function batchedUpdates(callback, a, b) { +function batchedUpdates(callback, a, b, c, d) { ensureInjected(); - batchingStrategy.batchedUpdates(callback, a, b); + batchingStrategy.batchedUpdates(callback, a, b, c, d); } /** - * Array comparator for ReactComponents by owner depth + * Array comparator for ReactComponents by mount ordering. * * @param {ReactComponent} c1 first component you're comparing * @param {ReactComponent} c2 second component you're comparing * @return {number} Return value usable by Array.prototype.sort(). */ -function mountDepthComparator(c1, c2) { - return c1._mountDepth - c2._mountDepth; +function mountOrderComparator(c1, c2) { + return c1._mountOrder - c2._mountOrder; } function runBatchedUpdates(transaction) { @@ -18273,69 +19847,68 @@ function runBatchedUpdates(transaction) { // Since reconciling a component higher in the owner hierarchy usually (not // always -- see shouldComponentUpdate()) will reconcile children, reconcile // them before their children by sorting the array. - dirtyComponents.sort(mountDepthComparator); + dirtyComponents.sort(mountOrderComparator); for (var i = 0; i < len; i++) { - // If a component is unmounted before pending changes apply, ignore them - // TODO: Queue unmounts in the same list to avoid this happening at all + // If a component is unmounted before pending changes apply, it will still + // be here, but we assume that it has cleared its _pendingCallbacks and + // that performUpdateIfNecessary is a noop. var component = dirtyComponents[i]; - if (component.isMounted()) { - // If performUpdateIfNecessary happens to enqueue any new updates, we - // shouldn't execute the callbacks until the next render happens, so - // stash the callbacks first - var callbacks = component._pendingCallbacks; - component._pendingCallbacks = null; - component.performUpdateIfNecessary(transaction.reconcileTransaction); - - if (callbacks) { - for (var j = 0; j < callbacks.length; j++) { - transaction.callbackQueue.enqueue( - callbacks[j], - component - ); - } + + // If performUpdateIfNecessary happens to enqueue any new updates, we + // shouldn't execute the callbacks until the next render happens, so + // stash the callbacks first + var callbacks = component._pendingCallbacks; + component._pendingCallbacks = null; + + ReactReconciler.performUpdateIfNecessary( + component, + transaction.reconcileTransaction + ); + + if (callbacks) { + for (var j = 0; j < callbacks.length; j++) { + transaction.callbackQueue.enqueue( + callbacks[j], + component.getPublicInstance() + ); } } } } -var flushBatchedUpdates = ReactPerf.measure( - 'ReactUpdates', - 'flushBatchedUpdates', - function() { - // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents - // array and perform any updates enqueued by mount-ready handlers (i.e., - // componentDidUpdate) but we need to check here too in order to catch - // updates enqueued by setState callbacks and asap calls. - while (dirtyComponents.length || asapEnqueued) { - if (dirtyComponents.length) { - var transaction = ReactUpdatesFlushTransaction.getPooled(); - transaction.perform(runBatchedUpdates, null, transaction); - ReactUpdatesFlushTransaction.release(transaction); - } +var flushBatchedUpdates = function() { + // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents + // array and perform any updates enqueued by mount-ready handlers (i.e., + // componentDidUpdate) but we need to check here too in order to catch + // updates enqueued by setState callbacks and asap calls. + while (dirtyComponents.length || asapEnqueued) { + if (dirtyComponents.length) { + var transaction = ReactUpdatesFlushTransaction.getPooled(); + transaction.perform(runBatchedUpdates, null, transaction); + ReactUpdatesFlushTransaction.release(transaction); + } - if (asapEnqueued) { - asapEnqueued = false; - var queue = asapCallbackQueue; - asapCallbackQueue = CallbackQueue.getPooled(); - queue.notifyAll(); - CallbackQueue.release(queue); - } + if (asapEnqueued) { + asapEnqueued = false; + var queue = asapCallbackQueue; + asapCallbackQueue = CallbackQueue.getPooled(); + queue.notifyAll(); + CallbackQueue.release(queue); } } +}; +flushBatchedUpdates = ReactPerf.measure( + 'ReactUpdates', + 'flushBatchedUpdates', + flushBatchedUpdates ); /** * Mark a component as needing a rerender, adding an optional callback to a * list of functions which will be executed once the rerender occurs. */ -function enqueueUpdate(component, callback) { - ("production" !== process.env.NODE_ENV ? invariant( - !callback || typeof callback === "function", - 'enqueueUpdate(...): You called `setProps`, `replaceProps`, ' + - '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + - 'isn\'t callable.' - ) : invariant(!callback || typeof callback === "function")); +function enqueueUpdate(component) { ensureInjected(); // Various parts of our code (such as ReactCompositeComponent's @@ -18352,19 +19925,11 @@ function enqueueUpdate(component, callback) { ) : null); if (!batchingStrategy.isBatchingUpdates) { - batchingStrategy.batchedUpdates(enqueueUpdate, component, callback); + batchingStrategy.batchedUpdates(enqueueUpdate, component); return; } dirtyComponents.push(component); - - if (callback) { - if (component._pendingCallbacks) { - component._pendingCallbacks.push(callback); - } else { - component._pendingCallbacks = [callback]; - } - } } /** @@ -18426,10 +19991,10 @@ var ReactUpdates = { module.exports = ReactUpdates; }).call(this,require('_process')) -},{"./CallbackQueue":48,"./Object.assign":70,"./PooledClass":71,"./ReactCurrentOwner":83,"./ReactPerf":116,"./Transaction":149,"./invariant":182,"./warning":202,"_process":1}],133:[function(require,module,exports){ +},{"./CallbackQueue":45,"./Object.assign":67,"./PooledClass":68,"./ReactCurrentOwner":83,"./ReactPerf":120,"./ReactReconciler":127,"./Transaction":155,"./invariant":189,"./warning":210,"_process":1}],139:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18446,13 +20011,14 @@ module.exports = ReactUpdates; * place to live inside React core. */ -"use strict"; +'use strict'; var LinkedStateMixin = require("./LinkedStateMixin"); var React = require("./React"); var ReactComponentWithPureRenderMixin = require("./ReactComponentWithPureRenderMixin"); var ReactCSSTransitionGroup = require("./ReactCSSTransitionGroup"); +var ReactFragment = require("./ReactFragment"); var ReactTransitionGroup = require("./ReactTransitionGroup"); var ReactUpdates = require("./ReactUpdates"); @@ -18469,6 +20035,7 @@ React.addons = { batchedUpdates: ReactUpdates.batchedUpdates, classSet: cx, cloneWithProps: cloneWithProps, + createFragment: ReactFragment.create, update: update }; @@ -18480,9 +20047,9 @@ if ("production" !== process.env.NODE_ENV) { module.exports = React; }).call(this,require('_process')) -},{"./LinkedStateMixin":66,"./React":72,"./ReactCSSTransitionGroup":75,"./ReactComponentWithPureRenderMixin":80,"./ReactDefaultPerf":97,"./ReactTestUtils":127,"./ReactTransitionGroup":131,"./ReactUpdates":132,"./cloneWithProps":155,"./cx":160,"./update":201,"_process":1}],134:[function(require,module,exports){ +},{"./LinkedStateMixin":63,"./React":69,"./ReactCSSTransitionGroup":72,"./ReactComponentWithPureRenderMixin":80,"./ReactDefaultPerf":99,"./ReactFragment":107,"./ReactTestUtils":133,"./ReactTransitionGroup":136,"./ReactUpdates":138,"./cloneWithProps":161,"./cx":166,"./update":209,"_process":1}],140:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18494,7 +20061,7 @@ module.exports = React; /*jslint bitwise: true*/ -"use strict"; +'use strict'; var DOMProperty = require("./DOMProperty"); @@ -18572,9 +20139,9 @@ var SVGDOMPropertyConfig = { module.exports = SVGDOMPropertyConfig; -},{"./DOMProperty":53}],135:[function(require,module,exports){ +},{"./DOMProperty":49}],141:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18584,7 +20151,7 @@ module.exports = SVGDOMPropertyConfig; * @providesModule SelectEventPlugin */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPropagators = require("./EventPropagators"); @@ -18669,8 +20236,8 @@ function constructSelectEvent(nativeEvent) { // won't dispatch. if (mouseDown || activeElement == null || - activeElement != getActiveElement()) { - return; + activeElement !== getActiveElement()) { + return null; } // Only fire when selection has actually changed. @@ -18767,9 +20334,9 @@ var SelectEventPlugin = { module.exports = SelectEventPlugin; -},{"./EventConstants":58,"./EventPropagators":63,"./ReactInputSelection":106,"./SyntheticEvent":141,"./getActiveElement":169,"./isTextInputElement":185,"./keyOf":189,"./shallowEqual":197}],136:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPropagators":59,"./ReactInputSelection":109,"./SyntheticEvent":147,"./getActiveElement":175,"./isTextInputElement":192,"./keyOf":196,"./shallowEqual":205}],142:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18780,7 +20347,7 @@ module.exports = SelectEventPlugin; * @typechecks */ -"use strict"; +'use strict'; /** * Size of the reactRoot ID space. We generate random numbers for React root @@ -18798,10 +20365,10 @@ var ServerReactRootIndex = { module.exports = ServerReactRootIndex; -},{}],137:[function(require,module,exports){ +},{}],143:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -18811,7 +20378,7 @@ module.exports = ServerReactRootIndex; * @providesModule SimpleEventPlugin */ -"use strict"; +'use strict'; var EventConstants = require("./EventConstants"); var EventPluginUtils = require("./EventPluginUtils"); @@ -19087,8 +20654,8 @@ var topLevelEventsToDispatchConfig = { topWheel: eventTypes.wheel }; -for (var topLevelType in topLevelEventsToDispatchConfig) { - topLevelEventsToDispatchConfig[topLevelType].dependencies = [topLevelType]; +for (var type in topLevelEventsToDispatchConfig) { + topLevelEventsToDispatchConfig[type].dependencies = [type]; } var SimpleEventPlugin = { @@ -19226,9 +20793,9 @@ var SimpleEventPlugin = { module.exports = SimpleEventPlugin; }).call(this,require('_process')) -},{"./EventConstants":58,"./EventPluginUtils":62,"./EventPropagators":63,"./SyntheticClipboardEvent":138,"./SyntheticDragEvent":140,"./SyntheticEvent":141,"./SyntheticFocusEvent":142,"./SyntheticKeyboardEvent":144,"./SyntheticMouseEvent":145,"./SyntheticTouchEvent":146,"./SyntheticUIEvent":147,"./SyntheticWheelEvent":148,"./getEventCharCode":170,"./invariant":182,"./keyOf":189,"./warning":202,"_process":1}],138:[function(require,module,exports){ +},{"./EventConstants":54,"./EventPluginUtils":58,"./EventPropagators":59,"./SyntheticClipboardEvent":144,"./SyntheticDragEvent":146,"./SyntheticEvent":147,"./SyntheticFocusEvent":148,"./SyntheticKeyboardEvent":150,"./SyntheticMouseEvent":151,"./SyntheticTouchEvent":152,"./SyntheticUIEvent":153,"./SyntheticWheelEvent":154,"./getEventCharCode":176,"./invariant":189,"./keyOf":196,"./warning":210,"_process":1}],144:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19239,7 +20806,7 @@ module.exports = SimpleEventPlugin; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticEvent = require("./SyntheticEvent"); @@ -19271,10 +20838,9 @@ SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); module.exports = SyntheticClipboardEvent; - -},{"./SyntheticEvent":141}],139:[function(require,module,exports){ +},{"./SyntheticEvent":147}],145:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19285,7 +20851,7 @@ module.exports = SyntheticClipboardEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticEvent = require("./SyntheticEvent"); @@ -19317,10 +20883,9 @@ SyntheticEvent.augmentClass( module.exports = SyntheticCompositionEvent; - -},{"./SyntheticEvent":141}],140:[function(require,module,exports){ +},{"./SyntheticEvent":147}],146:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19331,7 +20896,7 @@ module.exports = SyntheticCompositionEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticMouseEvent = require("./SyntheticMouseEvent"); @@ -19357,9 +20922,9 @@ SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface); module.exports = SyntheticDragEvent; -},{"./SyntheticMouseEvent":145}],141:[function(require,module,exports){ +},{"./SyntheticMouseEvent":151}],147:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19370,7 +20935,7 @@ module.exports = SyntheticDragEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var PooledClass = require("./PooledClass"); @@ -19448,13 +21013,21 @@ assign(SyntheticEvent.prototype, { preventDefault: function() { this.defaultPrevented = true; var event = this.nativeEvent; - event.preventDefault ? event.preventDefault() : event.returnValue = false; + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } this.isDefaultPrevented = emptyFunction.thatReturnsTrue; }, stopPropagation: function() { var event = this.nativeEvent; - event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } this.isPropagationStopped = emptyFunction.thatReturnsTrue; }, @@ -19515,9 +21088,9 @@ PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler); module.exports = SyntheticEvent; -},{"./Object.assign":70,"./PooledClass":71,"./emptyFunction":163,"./getEventTarget":173}],142:[function(require,module,exports){ +},{"./Object.assign":67,"./PooledClass":68,"./emptyFunction":168,"./getEventTarget":179}],148:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19528,7 +21101,7 @@ module.exports = SyntheticEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticUIEvent = require("./SyntheticUIEvent"); @@ -19554,9 +21127,9 @@ SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); module.exports = SyntheticFocusEvent; -},{"./SyntheticUIEvent":147}],143:[function(require,module,exports){ +},{"./SyntheticUIEvent":153}],149:[function(require,module,exports){ /** - * Copyright 2013 Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19567,7 +21140,7 @@ module.exports = SyntheticFocusEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticEvent = require("./SyntheticEvent"); @@ -19600,10 +21173,9 @@ SyntheticEvent.augmentClass( module.exports = SyntheticInputEvent; - -},{"./SyntheticEvent":141}],144:[function(require,module,exports){ +},{"./SyntheticEvent":147}],150:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19614,7 +21186,7 @@ module.exports = SyntheticInputEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticUIEvent = require("./SyntheticUIEvent"); @@ -19688,9 +21260,9 @@ SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); module.exports = SyntheticKeyboardEvent; -},{"./SyntheticUIEvent":147,"./getEventCharCode":170,"./getEventKey":171,"./getEventModifierState":172}],145:[function(require,module,exports){ +},{"./SyntheticUIEvent":153,"./getEventCharCode":176,"./getEventKey":177,"./getEventModifierState":178}],151:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19701,7 +21273,7 @@ module.exports = SyntheticKeyboardEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticUIEvent = require("./SyntheticUIEvent"); var ViewportMetrics = require("./ViewportMetrics"); @@ -19739,9 +21311,7 @@ var MouseEventInterface = { buttons: null, relatedTarget: function(event) { return event.relatedTarget || ( - event.fromElement === event.srcElement ? - event.toElement : - event.fromElement + ((event.fromElement === event.srcElement ? event.toElement : event.fromElement)) ); }, // "Proprietary" Interface. @@ -19771,9 +21341,9 @@ SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); module.exports = SyntheticMouseEvent; -},{"./SyntheticUIEvent":147,"./ViewportMetrics":150,"./getEventModifierState":172}],146:[function(require,module,exports){ +},{"./SyntheticUIEvent":153,"./ViewportMetrics":156,"./getEventModifierState":178}],152:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19784,7 +21354,7 @@ module.exports = SyntheticMouseEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticUIEvent = require("./SyntheticUIEvent"); @@ -19819,9 +21389,9 @@ SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); module.exports = SyntheticTouchEvent; -},{"./SyntheticUIEvent":147,"./getEventModifierState":172}],147:[function(require,module,exports){ +},{"./SyntheticUIEvent":153,"./getEventModifierState":178}],153:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19832,7 +21402,7 @@ module.exports = SyntheticTouchEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticEvent = require("./SyntheticEvent"); @@ -19881,9 +21451,9 @@ SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface); module.exports = SyntheticUIEvent; -},{"./SyntheticEvent":141,"./getEventTarget":173}],148:[function(require,module,exports){ +},{"./SyntheticEvent":147,"./getEventTarget":179}],154:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19894,7 +21464,7 @@ module.exports = SyntheticUIEvent; * @typechecks static-only */ -"use strict"; +'use strict'; var SyntheticMouseEvent = require("./SyntheticMouseEvent"); @@ -19942,10 +21512,10 @@ SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); module.exports = SyntheticWheelEvent; -},{"./SyntheticMouseEvent":145}],149:[function(require,module,exports){ +},{"./SyntheticMouseEvent":151}],155:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -19955,7 +21525,7 @@ module.exports = SyntheticWheelEvent; * @providesModule Transaction */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -20007,7 +21577,7 @@ var invariant = require("./invariant"); * content. * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue * to preserve the `scrollTop` (an automatic scroll aware DOM). - * - (Future use case): Layout calculations before and after DOM upates. + * - (Future use case): Layout calculations before and after DOM updates. * * Transactional plugin API: * - A module that has an `initialize` method that returns any precomputation. @@ -20149,8 +21719,8 @@ var Mixin = { // close -- if it's still set to true in the finally block, it means // wrapper.close threw. errorThrown = true; - if (initData !== Transaction.OBSERVED_ERROR) { - wrapper.close && wrapper.close.call(this, initData); + if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) { + wrapper.close.call(this, initData); } errorThrown = false; } finally { @@ -20183,9 +21753,9 @@ var Transaction = { module.exports = Transaction; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],150:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],156:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20195,9 +21765,7 @@ module.exports = Transaction; * @providesModule ViewportMetrics */ -"use strict"; - -var getUnboundedScrollPosition = require("./getUnboundedScrollPosition"); +'use strict'; var ViewportMetrics = { @@ -20205,8 +21773,7 @@ var ViewportMetrics = { currentScrollTop: 0, - refreshScrollValues: function() { - var scrollPosition = getUnboundedScrollPosition(window); + refreshScrollValues: function(scrollPosition) { ViewportMetrics.currentScrollLeft = scrollPosition.x; ViewportMetrics.currentScrollTop = scrollPosition.y; } @@ -20215,10 +21782,10 @@ var ViewportMetrics = { module.exports = ViewportMetrics; -},{"./getUnboundedScrollPosition":178}],151:[function(require,module,exports){ +},{}],157:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20228,7 +21795,7 @@ module.exports = ViewportMetrics; * @providesModule accumulateInto */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -20281,9 +21848,9 @@ function accumulateInto(current, next) { module.exports = accumulateInto; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],152:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],158:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20295,7 +21862,7 @@ module.exports = accumulateInto; /* jslint bitwise:true */ -"use strict"; +'use strict'; var MOD = 65521; @@ -20315,9 +21882,9 @@ function adler32(data) { module.exports = adler32; -},{}],153:[function(require,module,exports){ +},{}],159:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20347,9 +21914,9 @@ function camelize(string) { module.exports = camelize; -},{}],154:[function(require,module,exports){ +},{}],160:[function(require,module,exports){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20389,21 +21956,21 @@ function camelizeStyleName(string) { module.exports = camelizeStyleName; -},{"./camelize":153}],155:[function(require,module,exports){ +},{"./camelize":159}],161:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @typechecks + * @typechecks static-only * @providesModule cloneWithProps */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); var ReactPropTransferer = require("./ReactPropTransferer"); @@ -20417,10 +21984,10 @@ var CHILDREN_PROP = keyOf({children: null}); * Sometimes you want to change the props of a child passed to you. Usually * this is to add a CSS class. * - * @param {object} child child component you'd like to clone - * @param {object} props props you'd like to modify. They will be merged - * as if you used `transferPropsTo()`. - * @return {object} a clone of child with props merged in. + * @param {ReactElement} child child element you'd like to clone + * @param {object} props props you'd like to modify. className and style will be + * merged automatically. + * @return {ReactElement} a clone of child with props merged in. */ function cloneWithProps(child, props) { if ("production" !== process.env.NODE_ENV) { @@ -20448,9 +22015,9 @@ function cloneWithProps(child, props) { module.exports = cloneWithProps; }).call(this,require('_process')) -},{"./ReactElement":99,"./ReactPropTransferer":117,"./keyOf":189,"./warning":202,"_process":1}],156:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactPropTransferer":121,"./keyOf":196,"./warning":210,"_process":1}],162:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20492,16 +22059,16 @@ function containsNode(outerNode, innerNode) { module.exports = containsNode; -},{"./isTextNode":186}],157:[function(require,module,exports){ +},{"./isTextNode":193}],163:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule createArrayFrom + * @providesModule createArrayFromMixed * @typechecks */ @@ -20551,10 +22118,10 @@ function hasArrayNature(obj) { * * This is mostly useful idiomatically: * - * var createArrayFrom = require('createArrayFrom'); + * var createArrayFromMixed = require('createArrayFromMixed'); * * function takesOneOrMoreThings(things) { - * things = createArrayFrom(things); + * things = createArrayFromMixed(things); * ... * } * @@ -20566,7 +22133,7 @@ function hasArrayNature(obj) { * @param {*} obj * @return {array} */ -function createArrayFrom(obj) { +function createArrayFromMixed(obj) { if (!hasArrayNature(obj)) { return [obj]; } else if (Array.isArray(obj)) { @@ -20576,12 +22143,12 @@ function createArrayFrom(obj) { } } -module.exports = createArrayFrom; +module.exports = createArrayFromMixed; -},{"./toArray":199}],158:[function(require,module,exports){ +},{"./toArray":207}],164:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20592,10 +22159,10 @@ module.exports = createArrayFrom; * @typechecks */ -"use strict"; +'use strict'; // Defeat circular references by requiring this directly. -var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactClass = require("./ReactClass"); var ReactElement = require("./ReactElement"); var invariant = require("./invariant"); @@ -20614,7 +22181,8 @@ var invariant = require("./invariant"); function createFullPageComponent(tag) { var elementFactory = ReactElement.createFactory(tag); - var FullPageComponent = ReactCompositeComponent.createClass({ + var FullPageComponent = ReactClass.createClass({ + tagName: tag.toUpperCase(), displayName: 'ReactFullPageComponent' + tag, componentWillUnmount: function() { @@ -20639,10 +22207,10 @@ function createFullPageComponent(tag) { module.exports = createFullPageComponent; }).call(this,require('_process')) -},{"./ReactCompositeComponent":81,"./ReactElement":99,"./invariant":182,"_process":1}],159:[function(require,module,exports){ +},{"./ReactClass":76,"./ReactElement":101,"./invariant":189,"_process":1}],165:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20657,7 +22225,7 @@ module.exports = createFullPageComponent; var ExecutionEnvironment = require("./ExecutionEnvironment"); -var createArrayFrom = require("./createArrayFrom"); +var createArrayFromMixed = require("./createArrayFromMixed"); var getMarkupWrap = require("./getMarkupWrap"); var invariant = require("./invariant"); @@ -20716,10 +22284,10 @@ function createNodesFromMarkup(markup, handleScript) { handleScript, 'createNodesFromMarkup(...): Unexpected <script> element rendered.' ) : invariant(handleScript)); - createArrayFrom(scripts).forEach(handleScript); + createArrayFromMixed(scripts).forEach(handleScript); } - var nodes = createArrayFrom(node.childNodes); + var nodes = createArrayFromMixed(node.childNodes); while (node.lastChild) { node.removeChild(node.lastChild); } @@ -20729,9 +22297,10 @@ function createNodesFromMarkup(markup, handleScript) { module.exports = createNodesFromMarkup; }).call(this,require('_process')) -},{"./ExecutionEnvironment":64,"./createArrayFrom":157,"./getMarkupWrap":174,"./invariant":182,"_process":1}],160:[function(require,module,exports){ +},{"./ExecutionEnvironment":60,"./createArrayFromMixed":163,"./getMarkupWrap":181,"./invariant":189,"_process":1}],166:[function(require,module,exports){ +(function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20756,7 +22325,22 @@ module.exports = createNodesFromMarkup; * @param [string ...] Variable list of classNames in the string case. * @return string Renderable space-separated CSS className. */ + +'use strict'; +var warning = require("./warning"); + +var warned = false; + function cx(classNames) { + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + warned, + 'React.addons.classSet will be deprecated in a future version. See ' + + 'http://fb.me/react-addons-classset' + ) : null); + warned = true; + } + if (typeof classNames == 'object') { return Object.keys(classNames).filter(function(className) { return classNames[className]; @@ -20768,9 +22352,10 @@ function cx(classNames) { module.exports = cx; -},{}],161:[function(require,module,exports){ +}).call(this,require('_process')) +},{"./warning":210,"_process":1}],167:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20781,7 +22366,7 @@ module.exports = cx; * @typechecks static-only */ -"use strict"; +'use strict'; var CSSProperty = require("./CSSProperty"); @@ -20826,60 +22411,9 @@ function dangerousStyleValue(name, value) { module.exports = dangerousStyleValue; -},{"./CSSProperty":46}],162:[function(require,module,exports){ -(function (process){ -/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule deprecated - */ - -var assign = require("./Object.assign"); -var warning = require("./warning"); - +},{"./CSSProperty":43}],168:[function(require,module,exports){ /** - * This will log a single deprecation notice per function and forward the call - * on to the new API. - * - * @param {string} namespace The namespace of the call, eg 'React' - * @param {string} oldName The old function name, eg 'renderComponent' - * @param {string} newName The new function name, eg 'render' - * @param {*} ctx The context this forwarded call should run in - * @param {function} fn The function to forward on to - * @return {*} Will be the value as returned from `fn` - */ -function deprecated(namespace, oldName, newName, ctx, fn) { - var warned = false; - if ("production" !== process.env.NODE_ENV) { - var newFn = function() { - ("production" !== process.env.NODE_ENV ? warning( - warned, - (namespace + "." + oldName + " will be deprecated in a future version. ") + - ("Use " + namespace + "." + newName + " instead.") - ) : null); - warned = true; - return fn.apply(ctx, arguments); - }; - newFn.displayName = (namespace + "_" + oldName); - // We need to make sure all properties of the original fn are copied over. - // In particular, this is needed to support PropTypes - return assign(newFn, fn); - } - - return fn; -} - -module.exports = deprecated; - -}).call(this,require('_process')) -},{"./Object.assign":70,"./warning":202,"_process":1}],163:[function(require,module,exports){ -/** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20911,10 +22445,10 @@ emptyFunction.thatReturnsArgument = function(arg) { return arg; }; module.exports = emptyFunction; -},{}],164:[function(require,module,exports){ +},{}],169:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -20935,27 +22469,26 @@ if ("production" !== process.env.NODE_ENV) { module.exports = emptyObject; }).call(this,require('_process')) -},{"_process":1}],165:[function(require,module,exports){ +},{"_process":1}],170:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule escapeTextForBrowser - * @typechecks static-only + * @providesModule escapeTextContentForBrowser */ -"use strict"; +'use strict'; var ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - "\"": """, - "'": "'" + '&': '&', + '>': '>', + '<': '<', + '"': '"', + '\'': ''' }; var ESCAPE_REGEX = /[&><"']/g; @@ -20970,28 +22503,99 @@ function escaper(match) { * @param {*} text Text value to escape. * @return {string} An escaped string. */ -function escapeTextForBrowser(text) { +function escapeTextContentForBrowser(text) { return ('' + text).replace(ESCAPE_REGEX, escaper); } -module.exports = escapeTextForBrowser; +module.exports = escapeTextContentForBrowser; -},{}],166:[function(require,module,exports){ +},{}],171:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule flattenChildren + * @providesModule findDOMNode + * @typechecks static-only */ -"use strict"; +'use strict'; + +var ReactCurrentOwner = require("./ReactCurrentOwner"); +var ReactInstanceMap = require("./ReactInstanceMap"); +var ReactMount = require("./ReactMount"); + +var invariant = require("./invariant"); +var isNode = require("./isNode"); +var warning = require("./warning"); -var ReactTextComponent = require("./ReactTextComponent"); +/** + * Returns the DOM node rendered by this element. + * + * @param {ReactComponent|DOMElement} componentOrElement + * @return {DOMElement} The root node of this element. + */ +function findDOMNode(componentOrElement) { + if ("production" !== process.env.NODE_ENV) { + var owner = ReactCurrentOwner.current; + if (owner !== null) { + ("production" !== process.env.NODE_ENV ? warning( + owner._warnedAboutRefsInRender, + '%s is accessing getDOMNode or findDOMNode inside its render(). ' + + 'render() should be a pure function of props and state. It should ' + + 'never access something that requires stale data from the previous ' + + 'render, such as refs. Move this logic to componentDidMount and ' + + 'componentDidUpdate instead.', + owner.getName() || 'A component' + ) : null); + owner._warnedAboutRefsInRender = true; + } + } + if (componentOrElement == null) { + return null; + } + if (isNode(componentOrElement)) { + return componentOrElement; + } + if (ReactInstanceMap.has(componentOrElement)) { + return ReactMount.getNodeFromInstance(componentOrElement); + } + ("production" !== process.env.NODE_ENV ? invariant( + componentOrElement.render == null || + typeof componentOrElement.render !== 'function', + 'Component (with keys: %s) contains `render` method ' + + 'but is not mounted in the DOM', + Object.keys(componentOrElement) + ) : invariant(componentOrElement.render == null || + typeof componentOrElement.render !== 'function')); + ("production" !== process.env.NODE_ENV ? invariant( + false, + 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', + Object.keys(componentOrElement) + ) : invariant(false)); +} + +module.exports = findDOMNode; + +}).call(this,require('_process')) +},{"./ReactCurrentOwner":83,"./ReactInstanceMap":111,"./ReactMount":115,"./invariant":189,"./isNode":191,"./warning":210,"_process":1}],172:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule flattenChildren + */ + +'use strict'; var traverseAllChildren = require("./traverseAllChildren"); var warning = require("./warning"); @@ -21005,26 +22609,17 @@ function flattenSingleChildIntoContext(traverseContext, child, name) { // We found a component instance. var result = traverseContext; var keyUnique = !result.hasOwnProperty(name); - ("production" !== process.env.NODE_ENV ? warning( - keyUnique, - 'flattenChildren(...): Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, only ' + - 'the first child will be used.', - name - ) : null); + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + keyUnique, + 'flattenChildren(...): Encountered two children with the same key, ' + + '`%s`. Child keys must be unique; when two children share a key, only ' + + 'the first child will be used.', + name + ) : null); + } if (keyUnique && child != null) { - var type = typeof child; - var normalizedValue; - - if (type === 'string') { - normalizedValue = ReactTextComponent(child); - } else if (type === 'number') { - normalizedValue = ReactTextComponent('' + child); - } else { - normalizedValue = child; - } - - result[name] = normalizedValue; + result[name] = child; } } @@ -21045,9 +22640,9 @@ function flattenChildren(children) { module.exports = flattenChildren; }).call(this,require('_process')) -},{"./ReactTextComponent":128,"./traverseAllChildren":200,"./warning":202,"_process":1}],167:[function(require,module,exports){ +},{"./traverseAllChildren":208,"./warning":210,"_process":1}],173:[function(require,module,exports){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21074,9 +22669,9 @@ function focusNode(node) { module.exports = focusNode; -},{}],168:[function(require,module,exports){ +},{}],174:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21086,7 +22681,7 @@ module.exports = focusNode; * @providesModule forEachAccumulated */ -"use strict"; +'use strict'; /** * @param {array} an "accumulation" of items which is either an Array or @@ -21105,9 +22700,9 @@ var forEachAccumulated = function(arr, cb, scope) { module.exports = forEachAccumulated; -},{}],169:[function(require,module,exports){ +},{}],175:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21134,9 +22729,9 @@ function getActiveElement() /*?DOMElement*/ { module.exports = getActiveElement; -},{}],170:[function(require,module,exports){ +},{}],176:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21147,7 +22742,7 @@ module.exports = getActiveElement; * @typechecks static-only */ -"use strict"; +'use strict'; /** * `charCode` represents the actual "character code" and is safe to use with @@ -21186,9 +22781,9 @@ function getEventCharCode(nativeEvent) { module.exports = getEventCharCode; -},{}],171:[function(require,module,exports){ +},{}],177:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21199,7 +22794,7 @@ module.exports = getEventCharCode; * @typechecks static-only */ -"use strict"; +'use strict'; var getEventCharCode = require("./getEventCharCode"); @@ -21291,9 +22886,9 @@ function getEventKey(nativeEvent) { module.exports = getEventKey; -},{"./getEventCharCode":170}],172:[function(require,module,exports){ +},{"./getEventCharCode":176}],178:[function(require,module,exports){ /** - * Copyright 2013 Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21304,7 +22899,7 @@ module.exports = getEventKey; * @typechecks static-only */ -"use strict"; +'use strict'; /** * Translation from modifier key to the associated property in the event. @@ -21338,9 +22933,9 @@ function getEventModifierState(nativeEvent) { module.exports = getEventModifierState; -},{}],173:[function(require,module,exports){ +},{}],179:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21351,7 +22946,7 @@ module.exports = getEventModifierState; * @typechecks static-only */ -"use strict"; +'use strict'; /** * Gets the target node from a native browser event by accounting for @@ -21369,10 +22964,54 @@ function getEventTarget(nativeEvent) { module.exports = getEventTarget; -},{}],174:[function(require,module,exports){ +},{}],180:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule getIteratorFn + * @typechecks static-only + */ + +'use strict'; + +/* global Symbol */ +var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. + +/** + * Returns the iterator method function contained on the iterable object. + * + * Be sure to invoke the function with the iterable as context: + * + * var iteratorFn = getIteratorFn(myIterable); + * if (iteratorFn) { + * var iterator = iteratorFn.call(myIterable); + * ... + * } + * + * @param {?object} maybeIterable + * @return {?function} + */ +function getIteratorFn(maybeIterable) { + var iteratorFn = maybeIterable && ( + (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]) + ); + if (typeof iteratorFn === 'function') { + return iteratorFn; + } +} + +module.exports = getIteratorFn; + +},{}],181:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21486,9 +23125,9 @@ function getMarkupWrap(nodeName) { module.exports = getMarkupWrap; }).call(this,require('_process')) -},{"./ExecutionEnvironment":64,"./invariant":182,"_process":1}],175:[function(require,module,exports){ +},{"./ExecutionEnvironment":60,"./invariant":189,"_process":1}],182:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21498,7 +23137,7 @@ module.exports = getMarkupWrap; * @providesModule getNodeForCharacterOffset */ -"use strict"; +'use strict'; /** * Given any node return the first leaf node without children. @@ -21542,7 +23181,7 @@ function getNodeForCharacterOffset(root, offset) { var nodeEnd = 0; while (node) { - if (node.nodeType == 3) { + if (node.nodeType === 3) { nodeEnd = nodeStart + node.textContent.length; if (nodeStart <= offset && nodeEnd >= offset) { @@ -21561,9 +23200,9 @@ function getNodeForCharacterOffset(root, offset) { module.exports = getNodeForCharacterOffset; -},{}],176:[function(require,module,exports){ +},{}],183:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21573,7 +23212,7 @@ module.exports = getNodeForCharacterOffset; * @providesModule getReactRootElementInContainer */ -"use strict"; +'use strict'; var DOC_NODE_TYPE = 9; @@ -21596,9 +23235,9 @@ function getReactRootElementInContainer(container) { module.exports = getReactRootElementInContainer; -},{}],177:[function(require,module,exports){ +},{}],184:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21608,7 +23247,7 @@ module.exports = getReactRootElementInContainer; * @providesModule getTextContentAccessor */ -"use strict"; +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -21633,9 +23272,9 @@ function getTextContentAccessor() { module.exports = getTextContentAccessor; -},{"./ExecutionEnvironment":64}],178:[function(require,module,exports){ +},{"./ExecutionEnvironment":60}],185:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21673,9 +23312,9 @@ function getUnboundedScrollPosition(scrollable) { module.exports = getUnboundedScrollPosition; -},{}],179:[function(require,module,exports){ +},{}],186:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21706,9 +23345,9 @@ function hyphenate(string) { module.exports = hyphenate; -},{}],180:[function(require,module,exports){ +},{}],187:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21747,10 +23386,10 @@ function hyphenateStyleName(string) { module.exports = hyphenateStyleName; -},{"./hyphenate":179}],181:[function(require,module,exports){ +},{"./hyphenate":186}],188:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21761,99 +23400,122 @@ module.exports = hyphenateStyleName; * @typechecks static-only */ -"use strict"; +'use strict'; +var ReactCompositeComponent = require("./ReactCompositeComponent"); +var ReactEmptyComponent = require("./ReactEmptyComponent"); +var ReactNativeComponent = require("./ReactNativeComponent"); + +var assign = require("./Object.assign"); +var invariant = require("./invariant"); var warning = require("./warning"); -var ReactElement = require("./ReactElement"); -var ReactLegacyElement = require("./ReactLegacyElement"); -var ReactNativeComponent = require("./ReactNativeComponent"); -var ReactEmptyComponent = require("./ReactEmptyComponent"); +// To avoid a cyclic dependency, we create the final class in this module +var ReactCompositeComponentWrapper = function() { }; +assign( + ReactCompositeComponentWrapper.prototype, + ReactCompositeComponent.Mixin, + { + _instantiateReactComponent: instantiateReactComponent + } +); /** - * Given an `element` create an instance that will actually be mounted. + * Check if the type reference is a known internal type. I.e. not a user + * provided composite type. * - * @param {object} element + * @param {function} type + * @return {boolean} Returns true if this is a valid internal type. + */ +function isInternalComponentType(type) { + return ( + typeof type === 'function' && + typeof type.prototype.mountComponent === 'function' && + typeof type.prototype.receiveComponent === 'function' + ); +} + +/** + * Given a ReactNode, create an instance that will actually be mounted. + * + * @param {ReactNode} node * @param {*} parentCompositeType The composite type that resolved this. * @return {object} A new instance of the element's constructor. * @protected */ -function instantiateReactComponent(element, parentCompositeType) { +function instantiateReactComponent(node, parentCompositeType) { var instance; - if ("production" !== process.env.NODE_ENV) { - ("production" !== process.env.NODE_ENV ? warning( - element && (typeof element.type === 'function' || - typeof element.type === 'string'), - 'Only functions or strings can be mounted as React components.' - ) : null); - - // Resolve mock instances - if (element.type._mockedReactClassConstructor) { - // If this is a mocked class, we treat the legacy factory as if it was the - // class constructor for future proofing unit tests. Because this might - // be mocked as a legacy factory, we ignore any warnings triggerd by - // this temporary hack. - ReactLegacyElement._isLegacyCallWarningEnabled = false; - try { - instance = new element.type._mockedReactClassConstructor( - element.props - ); - } finally { - ReactLegacyElement._isLegacyCallWarningEnabled = true; - } - - // If the mock implementation was a legacy factory, then it returns a - // element. We need to turn this into a real component instance. - if (ReactElement.isValidElement(instance)) { - instance = new instance.type(instance.props); - } + if (node === null || node === false) { + node = ReactEmptyComponent.emptyElement; + } - var render = instance.render; - if (!render) { - // For auto-mocked factories, the prototype isn't shimmed and therefore - // there is no render function on the instance. We replace the whole - // component with an empty component instance instead. - element = ReactEmptyComponent.getEmptyComponent(); - } else { - if (render._isMockFunction && !render._getMockImplementation()) { - // Auto-mocked components may have a prototype with a mocked render - // function. For those, we'll need to mock the result of the render - // since we consider undefined to be invalid results from render. - render.mockImplementation( - ReactEmptyComponent.getEmptyComponent - ); - } - instance.construct(element); - return instance; - } + if (typeof node === 'object') { + var element = node; + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + element && (typeof element.type === 'function' || + typeof element.type === 'string'), + 'Only functions or strings can be mounted as React components.' + ) : null); } - } - // Special case string values - if (typeof element.type === 'string') { - instance = ReactNativeComponent.createInstanceForTag( - element.type, - element.props, - parentCompositeType - ); + // Special case string values + if (parentCompositeType === element.type && + typeof element.type === 'string') { + // Avoid recursion if the wrapper renders itself. + instance = ReactNativeComponent.createInternalComponent(element); + // All native components are currently wrapped in a composite so we're + // safe to assume that this is what we should instantiate. + } else if (isInternalComponentType(element.type)) { + // This is temporarily available for custom components that are not string + // represenations. I.e. ART. Once those are updated to use the string + // representation, we can drop this code path. + instance = new element.type(element); + } else { + instance = new ReactCompositeComponentWrapper(); + } + } else if (typeof node === 'string' || typeof node === 'number') { + instance = ReactNativeComponent.createInstanceForText(node); } else { - // Normal case for non-mocks and non-strings - instance = new element.type(element.props); + ("production" !== process.env.NODE_ENV ? invariant( + false, + 'Encountered invalid React node of type %s', + typeof node + ) : invariant(false)); } if ("production" !== process.env.NODE_ENV) { ("production" !== process.env.NODE_ENV ? warning( typeof instance.construct === 'function' && typeof instance.mountComponent === 'function' && - typeof instance.receiveComponent === 'function', + typeof instance.receiveComponent === 'function' && + typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.' ) : null); } - // This actually sets up the internal instance. This will become decoupled - // from the public instance in a future diff. - instance.construct(element); + // Sets up the instance. This can probably just move into the constructor now. + instance.construct(node); + + // These two fields are used by the DOM and ART diffing algorithms + // respectively. Instead of using expandos on components, we should be + // storing the state needed by the diffing algorithms elsewhere. + instance._mountIndex = 0; + instance._mountImage = null; + + if ("production" !== process.env.NODE_ENV) { + instance._isOwnerNecessary = false; + instance._warnedAboutRefsInRender = false; + } + + // Internal instances should fully constructed at this point, so they should + // not get any new fields added to them at this point. + if ("production" !== process.env.NODE_ENV) { + if (Object.preventExtensions) { + Object.preventExtensions(instance); + } + } return instance; } @@ -21861,10 +23523,10 @@ function instantiateReactComponent(element, parentCompositeType) { module.exports = instantiateReactComponent; }).call(this,require('_process')) -},{"./ReactElement":99,"./ReactEmptyComponent":101,"./ReactLegacyElement":108,"./ReactNativeComponent":114,"./warning":202,"_process":1}],182:[function(require,module,exports){ +},{"./Object.assign":67,"./ReactCompositeComponent":81,"./ReactEmptyComponent":103,"./ReactNativeComponent":118,"./invariant":189,"./warning":210,"_process":1}],189:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21918,9 +23580,9 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; }).call(this,require('_process')) -},{"_process":1}],183:[function(require,module,exports){ +},{"_process":1}],190:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -21930,7 +23592,7 @@ module.exports = invariant; * @providesModule isEventSupported */ -"use strict"; +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -21983,9 +23645,9 @@ function isEventSupported(eventNameSuffix, capture) { module.exports = isEventSupported; -},{"./ExecutionEnvironment":64}],184:[function(require,module,exports){ +},{"./ExecutionEnvironment":60}],191:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22002,18 +23664,17 @@ module.exports = isEventSupported; */ function isNode(object) { return !!(object && ( - typeof Node === 'function' ? object instanceof Node : - typeof object === 'object' && - typeof object.nodeType === 'number' && - typeof object.nodeName === 'string' + ((typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && + typeof object.nodeType === 'number' && + typeof object.nodeName === 'string')) )); } module.exports = isNode; -},{}],185:[function(require,module,exports){ +},{}],192:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22023,7 +23684,7 @@ module.exports = isNode; * @providesModule isTextInputElement */ -"use strict"; +'use strict'; /** * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary @@ -22048,16 +23709,15 @@ var supportedInputTypes = { function isTextInputElement(elem) { return elem && ( - (elem.nodeName === 'INPUT' && supportedInputTypes[elem.type]) || - elem.nodeName === 'TEXTAREA' + (elem.nodeName === 'INPUT' && supportedInputTypes[elem.type] || elem.nodeName === 'TEXTAREA') ); } module.exports = isTextInputElement; -},{}],186:[function(require,module,exports){ +},{}],193:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22080,9 +23740,9 @@ function isTextNode(object) { module.exports = isTextNode; -},{"./isNode":184}],187:[function(require,module,exports){ +},{"./isNode":191}],194:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22093,7 +23753,7 @@ module.exports = isTextNode; * @typechecks static-only */ -"use strict"; +'use strict'; /** * Combines multiple className strings into one. @@ -22121,10 +23781,10 @@ function joinClasses(className/*, ... */) { module.exports = joinClasses; -},{}],188:[function(require,module,exports){ +},{}],195:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22135,7 +23795,7 @@ module.exports = joinClasses; * @typechecks static-only */ -"use strict"; +'use strict'; var invariant = require("./invariant"); @@ -22176,9 +23836,9 @@ var keyMirror = function(obj) { module.exports = keyMirror; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],189:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],196:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22212,9 +23872,9 @@ var keyOf = function(oneKeyObj) { module.exports = keyOf; -},{}],190:[function(require,module,exports){ +},{}],197:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22265,9 +23925,9 @@ function mapObject(object, callback, context) { module.exports = mapObject; -},{}],191:[function(require,module,exports){ +},{}],198:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22278,7 +23938,7 @@ module.exports = mapObject; * @typechecks static-only */ -"use strict"; +'use strict'; /** * Memoizes the return value of a function that accepts one string argument. @@ -22289,54 +23949,19 @@ module.exports = mapObject; function memoizeStringOnly(callback) { var cache = {}; return function(string) { - if (cache.hasOwnProperty(string)) { - return cache[string]; - } else { - return cache[string] = callback.call(this, string); + if (!cache.hasOwnProperty(string)) { + cache[string] = callback.call(this, string); } + return cache[string]; }; } module.exports = memoizeStringOnly; -},{}],192:[function(require,module,exports){ -(function (process){ -/** - * Copyright 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule monitorCodeUse - */ - -"use strict"; - -var invariant = require("./invariant"); - -/** - * Provides open-source compatible instrumentation for monitoring certain API - * uses before we're ready to issue a warning or refactor. It accepts an event - * name which may only contain the characters [a-z0-9_] and an optional data - * object with further information. - */ - -function monitorCodeUse(eventName, data) { - ("production" !== process.env.NODE_ENV ? invariant( - eventName && !/[^a-z0-9_]/.test(eventName), - 'You must provide an eventName using only the characters [a-z0-9_]' - ) : invariant(eventName && !/[^a-z0-9_]/.test(eventName))); -} - -module.exports = monitorCodeUse; - -}).call(this,require('_process')) -},{"./invariant":182,"_process":1}],193:[function(require,module,exports){ +},{}],199:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22345,7 +23970,7 @@ module.exports = monitorCodeUse; * * @providesModule onlyChild */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); @@ -22373,9 +23998,9 @@ function onlyChild(children) { module.exports = onlyChild; }).call(this,require('_process')) -},{"./ReactElement":99,"./invariant":182,"_process":1}],194:[function(require,module,exports){ +},{"./ReactElement":101,"./invariant":189,"_process":1}],200:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22401,9 +24026,9 @@ if (ExecutionEnvironment.canUseDOM) { module.exports = performance || {}; -},{"./ExecutionEnvironment":64}],195:[function(require,module,exports){ +},{"./ExecutionEnvironment":60}],201:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22429,9 +24054,37 @@ var performanceNow = performance.now.bind(performance); module.exports = performanceNow; -},{"./performance":194}],196:[function(require,module,exports){ +},{"./performance":200}],202:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule quoteAttributeValueForBrowser + */ + +'use strict'; + +var escapeTextContentForBrowser = require("./escapeTextContentForBrowser"); + +/** + * Escapes attribute value to prevent scripting attacks. + * + * @param {*} value Value to escape. + * @return {string} An escaped string. + */ +function quoteAttributeValueForBrowser(value) { + return '"' + escapeTextContentForBrowser(value) + '"'; +} + +module.exports = quoteAttributeValueForBrowser; + +},{"./escapeTextContentForBrowser":170}],203:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22441,7 +24094,9 @@ module.exports = performanceNow; * @providesModule setInnerHTML */ -"use strict"; +/* globals MSApp */ + +'use strict'; var ExecutionEnvironment = require("./ExecutionEnvironment"); @@ -22460,6 +24115,15 @@ var setInnerHTML = function(node, html) { node.innerHTML = html; }; +// Win8 apps: Allow all html to be inserted +if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) { + setInnerHTML = function(node, html) { + MSApp.execUnsafeLocalFunction(function() { + node.innerHTML = html; + }); + }; +} + if (ExecutionEnvironment.canUseDOM) { // IE8: When updating a just created node with innerHTML only leading // whitespace is removed. When updating an existing node with innerHTML @@ -22507,9 +24171,51 @@ if (ExecutionEnvironment.canUseDOM) { module.exports = setInnerHTML; -},{"./ExecutionEnvironment":64}],197:[function(require,module,exports){ +},{"./ExecutionEnvironment":60}],204:[function(require,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule setTextContent + */ + +'use strict'; + +var ExecutionEnvironment = require("./ExecutionEnvironment"); +var escapeTextContentForBrowser = require("./escapeTextContentForBrowser"); +var setInnerHTML = require("./setInnerHTML"); + +/** + * Set the textContent property of a node, ensuring that whitespace is preserved + * even in IE8. innerText is a poor substitute for textContent and, among many + * issues, inserts <br> instead of the literal newline chars. innerHTML behaves + * as it should. + * + * @param {DOMElement} node + * @param {string} text + * @internal + */ +var setTextContent = function(node, text) { + node.textContent = text; +}; + +if (ExecutionEnvironment.canUseDOM) { + if (!('textContent' in document.documentElement)) { + setTextContent = function(node, text) { + setInnerHTML(node, escapeTextContentForBrowser(text)); + }; + } +} + +module.exports = setTextContent; + +},{"./ExecutionEnvironment":60,"./escapeTextContentForBrowser":170,"./setInnerHTML":203}],205:[function(require,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22519,7 +24225,7 @@ module.exports = setInnerHTML; * @providesModule shallowEqual */ -"use strict"; +'use strict'; /** * Performs equality by iterating through keys on an object and returning @@ -22551,9 +24257,10 @@ function shallowEqual(objA, objB) { module.exports = shallowEqual; -},{}],198:[function(require,module,exports){ +},{}],206:[function(require,module,exports){ +(function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22564,7 +24271,9 @@ module.exports = shallowEqual; * @typechecks static-only */ -"use strict"; +'use strict'; + +var warning = require("./warning"); /** * Given a `prevElement` and `nextElement`, determines if the existing @@ -22578,21 +24287,84 @@ module.exports = shallowEqual; * @protected */ function shouldUpdateReactComponent(prevElement, nextElement) { - if (prevElement && nextElement && - prevElement.type === nextElement.type && - prevElement.key === nextElement.key && - prevElement._owner === nextElement._owner) { - return true; + if (prevElement != null && nextElement != null) { + var prevType = typeof prevElement; + var nextType = typeof nextElement; + if (prevType === 'string' || prevType === 'number') { + return (nextType === 'string' || nextType === 'number'); + } else { + if (nextType === 'object' && + prevElement.type === nextElement.type && + prevElement.key === nextElement.key) { + var ownersMatch = prevElement._owner === nextElement._owner; + var prevName = null; + var nextName = null; + var nextDisplayName = null; + if ("production" !== process.env.NODE_ENV) { + if (!ownersMatch) { + if (prevElement._owner != null && + prevElement._owner.getPublicInstance() != null && + prevElement._owner.getPublicInstance().constructor != null) { + prevName = + prevElement._owner.getPublicInstance().constructor.displayName; + } + if (nextElement._owner != null && + nextElement._owner.getPublicInstance() != null && + nextElement._owner.getPublicInstance().constructor != null) { + nextName = + nextElement._owner.getPublicInstance().constructor.displayName; + } + if (nextElement.type != null && + nextElement.type.displayName != null) { + nextDisplayName = nextElement.type.displayName; + } + if (nextElement.type != null && typeof nextElement.type === 'string') { + nextDisplayName = nextElement.type; + } + if (typeof nextElement.type !== 'string' || + nextElement.type === 'input' || + nextElement.type === 'textarea') { + if ((prevElement._owner != null && + prevElement._owner._isOwnerNecessary === false) || + (nextElement._owner != null && + nextElement._owner._isOwnerNecessary === false)) { + if (prevElement._owner != null) { + prevElement._owner._isOwnerNecessary = true; + } + if (nextElement._owner != null) { + nextElement._owner._isOwnerNecessary = true; + } + ("production" !== process.env.NODE_ENV ? warning( + false, + '<%s /> is being rendered by both %s and %s using the same ' + + 'key (%s) in the same place. Currently, this means that ' + + 'they don\'t preserve state. This behavior should be very ' + + 'rare so we\'re considering deprecating it. Please contact ' + + 'the React team and explain your use case so that we can ' + + 'take that into consideration.', + nextDisplayName || 'Unknown Component', + prevName || '[Unknown]', + nextName || '[Unknown]', + prevElement.key + ) : null); + } + } + } + } + return ownersMatch; + } + } } return false; } module.exports = shouldUpdateReactComponent; -},{}],199:[function(require,module,exports){ +}).call(this,require('_process')) +},{"./warning":210,"_process":1}],207:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22609,7 +24381,7 @@ var invariant = require("./invariant"); * Convert array-like objects to arrays. * * This API assumes the caller knows the contents of the data type. For less - * well defined inputs use createArrayFrom. + * well defined inputs use createArrayFromMixed. * * @param {object|function|filelist} obj * @return {array} @@ -22661,10 +24433,10 @@ function toArray(obj) { module.exports = toArray; }).call(this,require('_process')) -},{"./invariant":182,"_process":1}],200:[function(require,module,exports){ +},{"./invariant":189,"_process":1}],208:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22674,22 +24446,22 @@ module.exports = toArray; * @providesModule traverseAllChildren */ -"use strict"; +'use strict'; var ReactElement = require("./ReactElement"); +var ReactFragment = require("./ReactFragment"); var ReactInstanceHandles = require("./ReactInstanceHandles"); +var getIteratorFn = require("./getIteratorFn"); var invariant = require("./invariant"); +var warning = require("./warning"); var SEPARATOR = ReactInstanceHandles.SEPARATOR; var SUBSEPARATOR = ':'; /** - * TODO: Test that: - * 1. `mapChildren` transforms strings and numbers into `ReactTextComponent`. - * 2. it('should fail when supplied duplicate key', function() { - * 3. That a single child and an array with one item have the same key pattern. - * }); + * TODO: Test that a single child and an array with one item have the same key + * pattern. */ var userProvidedKeyEscaperLookup = { @@ -22700,6 +24472,8 @@ var userProvidedKeyEscaperLookup = { var userProvidedKeyEscapeRegex = /[=.:]/g; +var didWarnAboutMaps = false; + function userProvidedKeyEscaper(match) { return userProvidedKeyEscaperLookup[match]; } @@ -22753,58 +24527,99 @@ function wrapUserProvidedKey(key) { * process. * @return {!number} The number of children in this subtree. */ -var traverseAllChildrenImpl = - function(children, nameSoFar, indexSoFar, callback, traverseContext) { - var nextName, nextIndex; - var subtreeCount = 0; // Count of children found in the current subtree. - if (Array.isArray(children)) { - for (var i = 0; i < children.length; i++) { - var child = children[i]; - nextName = ( - nameSoFar + - (nameSoFar ? SUBSEPARATOR : SEPARATOR) + - getComponentKey(child, i) - ); - nextIndex = indexSoFar + subtreeCount; - subtreeCount += traverseAllChildrenImpl( - child, - nextName, - nextIndex, - callback, - traverseContext - ); - } - } else { - var type = typeof children; - var isOnlyChild = nameSoFar === ''; +function traverseAllChildrenImpl( + children, + nameSoFar, + indexSoFar, + callback, + traverseContext +) { + var type = typeof children; + + if (type === 'undefined' || type === 'boolean') { + // All of the above are perceived as null. + children = null; + } + + if (children === null || + type === 'string' || + type === 'number' || + ReactElement.isValidElement(children)) { + callback( + traverseContext, + children, // If it's the only child, treat the name as if it was wrapped in an array - // so that it's consistent if the number of children grows - var storageName = - isOnlyChild ? SEPARATOR + getComponentKey(children, 0) : nameSoFar; - if (children == null || type === 'boolean') { - // All of the above are perceived as null. - callback(traverseContext, null, storageName, indexSoFar); - subtreeCount = 1; - } else if (type === 'string' || type === 'number' || - ReactElement.isValidElement(children)) { - callback(traverseContext, children, storageName, indexSoFar); - subtreeCount = 1; - } else if (type === 'object') { - ("production" !== process.env.NODE_ENV ? invariant( - !children || children.nodeType !== 1, - 'traverseAllChildren(...): Encountered an invalid child; DOM ' + - 'elements are not valid children of React components.' - ) : invariant(!children || children.nodeType !== 1)); - for (var key in children) { - if (children.hasOwnProperty(key)) { + // so that it's consistent if the number of children grows. + nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar, + indexSoFar + ); + return 1; + } + + var child, nextName, nextIndex; + var subtreeCount = 0; // Count of children found in the current subtree. + + if (Array.isArray(children)) { + for (var i = 0; i < children.length; i++) { + child = children[i]; + nextName = ( + (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + + getComponentKey(child, i) + ); + nextIndex = indexSoFar + subtreeCount; + subtreeCount += traverseAllChildrenImpl( + child, + nextName, + nextIndex, + callback, + traverseContext + ); + } + } else { + var iteratorFn = getIteratorFn(children); + if (iteratorFn) { + var iterator = iteratorFn.call(children); + var step; + if (iteratorFn !== children.entries) { + var ii = 0; + while (!(step = iterator.next()).done) { + child = step.value; + nextName = ( + (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + + getComponentKey(child, ii++) + ); + nextIndex = indexSoFar + subtreeCount; + subtreeCount += traverseAllChildrenImpl( + child, + nextName, + nextIndex, + callback, + traverseContext + ); + } + } else { + if ("production" !== process.env.NODE_ENV) { + ("production" !== process.env.NODE_ENV ? warning( + didWarnAboutMaps, + 'Using Maps as children is not yet fully supported. It is an ' + + 'experimental feature that might be removed. Convert it to a ' + + 'sequence / iterable of keyed ReactElements instead.' + ) : null); + didWarnAboutMaps = true; + } + // Iterator will provide entry [k,v] tuples rather than values. + while (!(step = iterator.next()).done) { + var entry = step.value; + if (entry) { + child = entry[1]; nextName = ( - nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + - wrapUserProvidedKey(key) + SUBSEPARATOR + - getComponentKey(children[key], 0) + (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + + wrapUserProvidedKey(entry[0]) + SUBSEPARATOR + + getComponentKey(child, 0) ); nextIndex = indexSoFar + subtreeCount; subtreeCount += traverseAllChildrenImpl( - children[key], + child, nextName, nextIndex, callback, @@ -22813,9 +24628,36 @@ var traverseAllChildrenImpl = } } } + } else if (type === 'object') { + ("production" !== process.env.NODE_ENV ? invariant( + children.nodeType !== 1, + 'traverseAllChildren(...): Encountered an invalid child; DOM ' + + 'elements are not valid children of React components.' + ) : invariant(children.nodeType !== 1)); + var fragment = ReactFragment.extract(children); + for (var key in fragment) { + if (fragment.hasOwnProperty(key)) { + child = fragment[key]; + nextName = ( + (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + + wrapUserProvidedKey(key) + SUBSEPARATOR + + getComponentKey(child, 0) + ); + nextIndex = indexSoFar + subtreeCount; + subtreeCount += traverseAllChildrenImpl( + child, + nextName, + nextIndex, + callback, + traverseContext + ); + } + } } - return subtreeCount; - }; + } + + return subtreeCount; +} /** * Traverses children that are typically specified as `props.children`, but @@ -22844,10 +24686,10 @@ function traverseAllChildren(children, callback, traverseContext) { module.exports = traverseAllChildren; }).call(this,require('_process')) -},{"./ReactElement":99,"./ReactInstanceHandles":107,"./invariant":182,"_process":1}],201:[function(require,module,exports){ +},{"./ReactElement":101,"./ReactFragment":107,"./ReactInstanceHandles":110,"./getIteratorFn":180,"./invariant":189,"./warning":210,"_process":1}],209:[function(require,module,exports){ (function (process){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -22857,7 +24699,7 @@ module.exports = traverseAllChildren; * @providesModule update */ -"use strict"; +'use strict'; var assign = require("./Object.assign"); var keyOf = require("./keyOf"); @@ -23012,10 +24854,10 @@ function update(value, spec) { module.exports = update; }).call(this,require('_process')) -},{"./Object.assign":70,"./invariant":182,"./keyOf":189,"_process":1}],202:[function(require,module,exports){ +},{"./Object.assign":67,"./invariant":189,"./keyOf":196,"_process":1}],210:[function(require,module,exports){ (function (process){ /** - * Copyright 2014, Facebook, Inc. + * Copyright 2014-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -23039,7 +24881,7 @@ var emptyFunction = require("./emptyFunction"); var warning = emptyFunction; if ("production" !== process.env.NODE_ENV) { - warning = function(condition, format ) {var args=Array.prototype.slice.call(arguments,2); + warning = function(condition, format ) {for (var args=[],$__0=2,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); if (format === undefined) { throw new Error( '`warning(condition, format, ...args)` requires a warning ' + @@ -23047,9 +24889,27 @@ if ("production" !== process.env.NODE_ENV) { ); } + if (format.length < 10 || /^[s\W]*$/.test(format)) { + throw new Error( + 'The warning format should be able to uniquely identify this ' + + 'warning. Please, use a more descriptive format than: ' + format + ); + } + + if (format.indexOf('Failed Composite propType: ') === 0) { + return; // Ignore CompositeComponent proptype check. + } + if (!condition) { var argIndex = 0; - console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];})); + var message = 'Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];}); + console.warn(message); + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch(x) {} } }; } @@ -23057,7 +24917,7 @@ if ("production" !== process.env.NODE_ENV) { module.exports = warning; }).call(this,require('_process')) -},{"./emptyFunction":163,"_process":1}],"flux":[function(require,module,exports){ +},{"./emptyFunction":168,"_process":1}],"flux":[function(require,module,exports){ /** * Copyright (c) 2014, Facebook, Inc. * All rights reserved. @@ -43899,7 +45759,6 @@ exports.ScrollToTopBehavior = require("./behaviors/ScrollToTopBehavior"); exports.History = require("./History"); exports.Navigation = require("./Navigation"); -exports.RouteHandlerMixin = require("./RouteHandlerMixin"); exports.State = require("./State"); exports.createRoute = require("./Route").createRoute; @@ -43909,10 +45768,10 @@ exports.createRedirect = require("./Route").createRedirect; exports.createRoutesFromReactChildren = require("./createRoutesFromReactChildren"); exports.create = require("./createRouter"); exports.run = require("./runRouter"); -},{"./History":6,"./Navigation":8,"./Route":13,"./RouteHandlerMixin":14,"./State":16,"./behaviors/ImitateBrowserBehavior":20,"./behaviors/ScrollToTopBehavior":21,"./components/DefaultRoute":22,"./components/Link":23,"./components/NotFoundRoute":24,"./components/Redirect":25,"./components/Route":26,"./components/RouteHandler":27,"./createRouter":28,"./createRoutesFromReactChildren":29,"./locations/HashLocation":32,"./locations/HistoryLocation":33,"./locations/RefreshLocation":34,"./locations/StaticLocation":35,"./runRouter":36}],"react/addons":[function(require,module,exports){ +},{"./History":10,"./Navigation":12,"./Route":16,"./State":18,"./behaviors/ImitateBrowserBehavior":21,"./behaviors/ScrollToTopBehavior":22,"./components/DefaultRoute":24,"./components/Link":25,"./components/NotFoundRoute":26,"./components/Redirect":27,"./components/Route":28,"./components/RouteHandler":29,"./createRouter":30,"./createRoutesFromReactChildren":31,"./locations/HashLocation":34,"./locations/HistoryLocation":35,"./locations/RefreshLocation":36,"./locations/StaticLocation":37,"./runRouter":38}],"react/addons":[function(require,module,exports){ module.exports = require('./lib/ReactWithAddons'); -},{"./lib/ReactWithAddons":133}],"react":[function(require,module,exports){ +},{"./lib/ReactWithAddons":139}],"react":[function(require,module,exports){ module.exports = require('./lib/React'); -},{"./lib/React":72}]},{},["jquery","lodash","react","react-router","flux","react/addons"]); +},{"./lib/React":69}]},{},["flux","jquery","lodash","react","react-router","react/addons"]); |