Comparing version 0.9.0 to 0.10.0-rc1
@@ -22,6 +22,8 @@ /** | ||
var focusNode = require("./focusNode"); | ||
var AutoFocusMixin = { | ||
componentDidMount: function() { | ||
if (this.props.autoFocus) { | ||
this.getDOMNode().focus(); | ||
focusNode(this.getDOMNode()); | ||
} | ||
@@ -28,0 +30,0 @@ } |
@@ -25,2 +25,3 @@ /** | ||
var keyOf = require("./keyOf"); | ||
var warning = require("./warning"); | ||
@@ -40,9 +41,8 @@ var CHILDREN_PROP = keyOf({children: null}); | ||
if ("production" !== process.env.NODE_ENV) { | ||
if (child.props.ref) { | ||
console.warn( | ||
'You are calling cloneWithProps() on a child with a ref. This is ' + | ||
'dangerous because you\'re creating a new child which will not be ' + | ||
'added as a ref to its parent.' | ||
); | ||
} | ||
("production" !== process.env.NODE_ENV ? warning( | ||
!child.props.ref, | ||
'You are calling cloneWithProps() on a child with a ref. This is ' + | ||
'dangerous because you\'re creating a new child which will not be ' + | ||
'added as a ref to its parent.' | ||
) : null); | ||
} | ||
@@ -49,0 +49,0 @@ |
@@ -117,2 +117,3 @@ /** | ||
srcDoc: MUST_USE_PROPERTY, | ||
srcSet: null, | ||
step: null, | ||
@@ -157,2 +158,3 @@ style: null, | ||
strokeWidth: MUST_USE_ATTRIBUTE, | ||
textAnchor: MUST_USE_ATTRIBUTE, | ||
transform: MUST_USE_ATTRIBUTE, | ||
@@ -178,2 +180,3 @@ version: MUST_USE_ATTRIBUTE, | ||
strokeWidth: 'stroke-width', | ||
textAnchor: 'text-anchor', | ||
viewBox: 'viewBox' | ||
@@ -191,14 +194,4 @@ }, | ||
spellCheck: 'spellcheck', | ||
srcDoc: 'srcdoc' | ||
}, | ||
DOMMutationMethods: { | ||
/** | ||
* Setting `className` to null may cause it to be set to the string "null". | ||
* | ||
* @param {DOMElement} node | ||
* @param {*} value | ||
*/ | ||
className: function(node, value) { | ||
node.className = value || ''; | ||
} | ||
srcDoc: 'srcdoc', | ||
srcSet: 'srcset' | ||
} | ||
@@ -205,0 +198,0 @@ }; |
@@ -60,10 +60,10 @@ /** | ||
/** | ||
* Sets the text content of `node` to `text`. | ||
* | ||
* @param {DOMElement} node Node to change | ||
* @param {string} text New text content | ||
*/ | ||
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) { | ||
@@ -73,2 +73,8 @@ 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) { | ||
@@ -75,0 +81,0 @@ // In order to preserve newlines correctly, we can't use .innerText to set |
@@ -237,7 +237,9 @@ /** | ||
isCustomAttribute: function(attributeName) { | ||
return DOMProperty._isCustomAttributeFunctions.some( | ||
function(isCustomAttributeFn) { | ||
return isCustomAttributeFn.call(null, attributeName); | ||
for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) { | ||
var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i]; | ||
if (isCustomAttributeFn(attributeName)) { | ||
return true; | ||
} | ||
); | ||
} | ||
return false; | ||
}, | ||
@@ -244,0 +246,0 @@ |
@@ -26,2 +26,3 @@ /** | ||
var memoizeStringOnly = require("./memoizeStringOnly"); | ||
var warning = require("./warning"); | ||
@@ -61,7 +62,6 @@ function shouldIgnoreValue(name, value) { | ||
// logging too much when using transferPropsTo. | ||
if (standardName != null) { | ||
console.warn( | ||
'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' | ||
); | ||
} | ||
("production" !== process.env.NODE_ENV ? warning( | ||
standardName == null, | ||
'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' | ||
) : null); | ||
@@ -167,3 +167,3 @@ }; | ||
node.nodeName, | ||
name | ||
propName | ||
); | ||
@@ -170,0 +170,0 @@ if (!DOMProperty.hasSideEffects[name] || |
@@ -29,2 +29,3 @@ /** | ||
var isEventSupported = require("./isEventSupported"); | ||
var monitorCodeUse = require("./monitorCodeUse"); | ||
@@ -172,2 +173,3 @@ /** | ||
!isEventSupported('scroll', true)) { | ||
monitorCodeUse('react_no_scroll_event'); | ||
console.warn('This browser doesn\'t support the `onScroll` event'); | ||
@@ -174,0 +176,0 @@ } |
@@ -26,3 +26,3 @@ /** | ||
return !!(object && ( | ||
typeof Node !== 'undefined' ? object instanceof Node : | ||
typeof Node === 'function' ? object instanceof Node : | ||
typeof object === 'object' && | ||
@@ -29,0 +29,0 @@ typeof object.nodeType === 'number' && |
@@ -25,2 +25,3 @@ /** | ||
var invariant = require("./invariant"); | ||
var warning = require("./warning"); | ||
@@ -88,14 +89,13 @@ var hasReadOnlyValue = { | ||
if ("production" !== process.env.NODE_ENV) { | ||
if (props[propName] && | ||
!hasReadOnlyValue[props.type] && | ||
!props.onChange && | ||
!props.readOnly && | ||
!props.disabled) { | ||
console.warn( | ||
'You provided a `value` prop to a form field without an ' + | ||
'`onChange` handler. This will render a read-only field. If ' + | ||
'the field should be mutable use `defaultValue`. Otherwise, ' + | ||
'set either `onChange` or `readOnly`.' | ||
); | ||
} | ||
("production" !== process.env.NODE_ENV ? warning( | ||
!props[propName] || | ||
hasReadOnlyValue[props.type] || | ||
props.onChange || | ||
props.readOnly || | ||
props.disabled, | ||
'You provided a `value` prop to a form field without an ' + | ||
'`onChange` handler. This will render a read-only field. If ' + | ||
'the field should be mutable use `defaultValue`. Otherwise, ' + | ||
'set either `onChange` or `readOnly`.' | ||
) : null); | ||
} | ||
@@ -105,13 +105,12 @@ }, | ||
if ("production" !== process.env.NODE_ENV) { | ||
if (props[propName] && | ||
!props.onChange && | ||
!props.readOnly && | ||
!props.disabled) { | ||
console.warn( | ||
'You provided a `checked` prop to a form field without an ' + | ||
'`onChange` handler. This will render a read-only field. If ' + | ||
'the field should be mutable use `defaultChecked`. Otherwise, ' + | ||
'set either `onChange` or `readOnly`.' | ||
); | ||
} | ||
("production" !== process.env.NODE_ENV ? warning( | ||
!props[propName] || | ||
props.onChange || | ||
props.readOnly || | ||
props.disabled, | ||
'You provided a `checked` prop to a form field without an ' + | ||
'`onChange` handler. This will render a read-only field. If ' + | ||
'the field should be mutable use `defaultChecked`. Otherwise, ' + | ||
'set either `onChange` or `readOnly`.' | ||
) : null); | ||
} | ||
@@ -118,0 +117,0 @@ }, |
@@ -63,2 +63,4 @@ /** | ||
renderComponentToString: ReactServerRendering.renderComponentToString, | ||
renderComponentToStaticMarkup: | ||
ReactServerRendering.renderComponentToStaticMarkup, | ||
unmountComponentAtNode: ReactMount.unmountComponentAtNode, | ||
@@ -94,4 +96,4 @@ isValidClass: ReactCompositeComponent.isValidClass, | ||
// internal version. | ||
React.version = '0.9.0'; | ||
React.version = '0.10.0-rc1'; | ||
module.exports = React; |
@@ -21,3 +21,2 @@ /** | ||
var ReactComponentEnvironment = require("./ReactComponentEnvironment"); | ||
var ReactCurrentOwner = require("./ReactCurrentOwner"); | ||
@@ -30,2 +29,3 @@ var ReactOwner = require("./ReactOwner"); | ||
var merge = require("./merge"); | ||
var monitorCodeUse = require("./monitorCodeUse"); | ||
@@ -55,6 +55,29 @@ /** | ||
var ownerHasPropertyWarning = {}; | ||
var ownerHasMonitoredObjectMap = {}; | ||
var NUMERIC_PROPERTY_REGEX = /^\d+$/; | ||
var injected = false; | ||
/** | ||
* Optionally injectable environment dependent cleanup hook. (server vs. | ||
* browser etc). Example: A browser system caches DOM nodes based on component | ||
* ID and must remove that cache entry when this instance is unmounted. | ||
* | ||
* @private | ||
*/ | ||
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; | ||
/** | ||
* Warn if the component doesn't have an explicit key assigned to it. | ||
@@ -88,5 +111,7 @@ * This component is in an array. The array could grow and shrink or be | ||
'Check the render method of ' + currentName + '.'; | ||
var childOwnerName = null; | ||
if (!component.isOwnedBy(ReactCurrentOwner.current)) { | ||
// Name of the component that originally created this child. | ||
var childOwnerName = | ||
childOwnerName = | ||
component._owner && | ||
@@ -102,2 +127,6 @@ component._owner.constructor.displayName; | ||
message += ' See http://fb.me/react-warning-keys for more information.'; | ||
monitorCodeUse('react_key_warning', { | ||
component: currentName, | ||
componentOwner: childOwnerName | ||
}); | ||
console.warn(message); | ||
@@ -123,2 +152,3 @@ } | ||
monitorCodeUse('react_numeric_key_warning'); | ||
console.warn( | ||
@@ -133,2 +163,21 @@ 'Child objects should have non-numeric keys so ordering is preserved. ' + | ||
/** | ||
* Log that we're using an object map. We're considering deprecating this | ||
* feature and replace it with proper Map and ImmutableMap data structures. | ||
* | ||
* @internal | ||
*/ | ||
function monitorUseOfObjectMap() { | ||
// Name of the component whose render method tried to pass children. | ||
// We only use this to avoid spewing the logs. We lose additional | ||
// owner stacks but hopefully one level is enough to trace the source. | ||
var currentName = (ReactCurrentOwner.current && | ||
ReactCurrentOwner.current.constructor.displayName) || ''; | ||
if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) { | ||
return; | ||
} | ||
ownerHasMonitoredObjectMap[currentName] = true; | ||
monitorCodeUse('react_object_map_children'); | ||
} | ||
/** | ||
* Ensure that every component either is passed in a static location, in an | ||
@@ -154,2 +203,3 @@ * array with an explicit keys property defined, or in an object literal | ||
} else if (component && typeof component === 'object') { | ||
monitorUseOfObjectMap(); | ||
for (var name in component) { | ||
@@ -188,2 +238,19 @@ validatePropertyKey(name, component); | ||
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; | ||
ReactComponent.ReactReconcileTransaction = | ||
ReactComponentEnvironment.ReactReconcileTransaction; | ||
injected = true; | ||
} | ||
}, | ||
/** | ||
@@ -221,25 +288,5 @@ * @param {?object} object | ||
*/ | ||
BackendIDOperations: ReactComponentEnvironment.BackendIDOperations, | ||
BackendIDOperations: null, | ||
/** | ||
* 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 | ||
*/ | ||
unmountIDFromEnvironment: ReactComponentEnvironment.unmountIDFromEnvironment, | ||
/** | ||
* 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 | ||
*/ | ||
mountImageIntoNode: ReactComponentEnvironment.mountImageIntoNode, | ||
/** | ||
* React references `ReactReconcileTransaction` using this property in order | ||
@@ -250,4 +297,3 @@ * to allow dependency injection. | ||
*/ | ||
ReactReconcileTransaction: | ||
ReactComponentEnvironment.ReactReconcileTransaction, | ||
ReactReconcileTransaction: null, | ||
@@ -260,3 +306,3 @@ /** | ||
*/ | ||
Mixin: merge(ReactComponentEnvironment.Mixin, { | ||
Mixin: { | ||
@@ -369,3 +415,3 @@ /** | ||
* @param {string} rootID DOM ID of the root node. | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @param {number} mountDepth number of components in the owner hierarchy. | ||
@@ -412,3 +458,3 @@ * @return {?string} Rendered markup to be inserted into the DOM. | ||
} | ||
ReactComponent.unmountIDFromEnvironment(this._rootNodeID); | ||
unmountIDFromEnvironment(this._rootNodeID); | ||
this._rootNodeID = null; | ||
@@ -442,3 +488,2 @@ this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; | ||
* | ||
* @param {ReactReconcileTransaction} transaction | ||
* @internal | ||
@@ -532,3 +577,3 @@ */ | ||
var markup = this.mountComponent(rootID, transaction, 0); | ||
ReactComponent.mountImageIntoNode(markup, container, shouldReuseMarkup); | ||
mountImageIntoNode(markup, container, shouldReuseMarkup); | ||
}, | ||
@@ -563,5 +608,5 @@ | ||
} | ||
}) | ||
} | ||
}; | ||
module.exports = ReactComponent; |
@@ -42,22 +42,2 @@ /** | ||
var ReactComponentBrowserEnvironment = { | ||
/** | ||
* Mixed into every component instance. | ||
*/ | ||
Mixin: { | ||
/** | ||
* Returns the DOM node rendered by this component. | ||
* | ||
* @return {DOMElement} The root node of this component. | ||
* @final | ||
* @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())); | ||
return ReactMount.getNode(this._rootNodeID); | ||
} | ||
}, | ||
ReactReconcileTransaction: ReactReconcileTransaction, | ||
@@ -140,17 +120,3 @@ | ||
// Asynchronously inject markup by ensuring that the container is not in | ||
// the document when settings its `innerHTML`. | ||
var parent = container.parentNode; | ||
if (parent) { | ||
var next = container.nextSibling; | ||
parent.removeChild(container); | ||
container.innerHTML = markup; | ||
if (next) { | ||
parent.insertBefore(container, next); | ||
} else { | ||
parent.appendChild(container); | ||
} | ||
} else { | ||
container.innerHTML = markup; | ||
} | ||
container.innerHTML = markup; | ||
} | ||
@@ -157,0 +123,0 @@ ) |
@@ -32,2 +32,3 @@ /** | ||
var instantiateReactComponent = require("./instantiateReactComponent"); | ||
var invariant = require("./invariant"); | ||
@@ -37,4 +38,6 @@ var keyMirror = require("./keyMirror"); | ||
var mixInto = require("./mixInto"); | ||
var monitorCodeUse = require("./monitorCodeUse"); | ||
var objMap = require("./objMap"); | ||
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); | ||
var warning = require("./warning"); | ||
@@ -66,2 +69,5 @@ /** | ||
var injectedMixins = []; | ||
/** | ||
@@ -506,3 +512,3 @@ * Composite components are higher-level components that compose other composite | ||
var property = statics[name]; | ||
if (!statics.hasOwnProperty(name) || !property) { | ||
if (!statics.hasOwnProperty(name)) { | ||
return; | ||
@@ -599,15 +605,48 @@ } | ||
isOwnedBy: true, // should be deprecated but can have code mod (internal) | ||
mountComponent: true, | ||
mountComponentIntoNode: true, | ||
type: true, | ||
props: true, | ||
type: true, | ||
_checkPropTypes: true, | ||
_mountComponentIntoNode: true, | ||
_processContext: true | ||
// currently private but belong on the descriptor and are valid for use | ||
// inside the framework: | ||
__keyValidated__: true, | ||
_owner: true, | ||
_currentContext: true | ||
}; | ||
var componentInstanceProperties = { | ||
__keyValidated__: true, | ||
__keySetters: true, | ||
_compositeLifeCycleState: true, | ||
_currentContext: true, | ||
_defaultProps: true, | ||
_instance: true, | ||
_lifeCycleState: true, | ||
_mountDepth: true, | ||
_owner: true, | ||
_pendingCallbacks: true, | ||
_pendingContext: true, | ||
_pendingForceUpdate: true, | ||
_pendingOwner: true, | ||
_pendingProps: true, | ||
_pendingState: true, | ||
_renderedComponent: true, | ||
_rootNodeID: true, | ||
context: true, | ||
props: true, | ||
refs: true, | ||
state: true, | ||
// These are known instance properties coming from other sources | ||
_pendingQueries: true, | ||
_queryPropListeners: true, | ||
queryParams: true | ||
}; | ||
var hasWarnedOnComponentType = {}; | ||
var warnIfUnmounted = function(instance, key) { | ||
if (instance.__hasBeenMounted) { | ||
var warningStackCounter = 0; | ||
var issueMembraneWarning = function(instance, key) { | ||
var isWhitelisted = unmountedPropertyWhitelist.hasOwnProperty(key); | ||
if (warningStackCounter > 0 || isWhitelisted) { | ||
return; | ||
@@ -628,2 +667,3 @@ } | ||
monitorCodeUse('react_descriptor_property_access', { component: name }); | ||
console.warn( | ||
@@ -636,2 +676,26 @@ 'Invalid access to component property "' + key + '" on ' + name + | ||
var wrapInMembraneFunction = function(fn, thisBinding) { | ||
if (fn.__reactMembraneFunction && fn.__reactMembraneSelf === thisBinding) { | ||
return fn.__reactMembraneFunction; | ||
} | ||
return fn.__reactMembraneFunction = function() { | ||
/** | ||
* By getting this function, you've already received a warning. The | ||
* internals of this function will likely cause more warnings. To avoid | ||
* Spamming too much we disable any warning triggered inside of this | ||
* stack. | ||
*/ | ||
warningStackCounter++; | ||
try { | ||
// If the this binding is unchanged, we defer to the real component. | ||
// This is important to keep some referential integrity in the | ||
// internals. E.g. owner equality check. | ||
var self = this === thisBinding ? this.__realComponentInstance : this; | ||
return fn.apply(self, arguments); | ||
} finally { | ||
warningStackCounter--; | ||
} | ||
}; | ||
}; | ||
var defineMembraneProperty = function(membrane, prototype, key) { | ||
@@ -644,27 +708,29 @@ Object.defineProperty(membrane, key, { | ||
get: function() { | ||
if (this !== membrane) { | ||
// When this is accessed through a prototype chain we need to check if | ||
// this component was mounted. | ||
warnIfUnmounted(this, key); | ||
if (this === membrane) { | ||
// We're allowed to access the prototype directly. | ||
return prototype[key]; | ||
} | ||
return prototype[key]; | ||
issueMembraneWarning(this, key); | ||
var realValue = this.__realComponentInstance[key]; | ||
// If the real value is a function, we need to provide a wrapper that | ||
// disables nested warnings. The properties type and constructors are | ||
// expected to the be constructors and therefore is often use with an | ||
// equality check and we shouldn't try to rebind those. | ||
if (typeof realValue === 'function' && | ||
key !== 'type' && | ||
key !== 'constructor') { | ||
return wrapInMembraneFunction(realValue, this); | ||
} | ||
return realValue; | ||
}, | ||
set: function(value) { | ||
if (this !== membrane) { | ||
// When this is accessed through a prototype chain, we first check if | ||
// this component was mounted. Then we define a value on "this" | ||
// instance, effectively disabling the membrane on that prototype | ||
// chain. | ||
warnIfUnmounted(this, key); | ||
Object.defineProperty(this, key, { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: value | ||
}); | ||
} else { | ||
// Otherwise, this should modify the prototype | ||
if (this === membrane) { | ||
// We're allowed to set a value on the prototype directly. | ||
prototype[key] = value; | ||
return; | ||
} | ||
issueMembraneWarning(this, key); | ||
this.__realComponentInstance[key] = value; | ||
} | ||
@@ -684,22 +750,47 @@ | ||
var createMountWarningMembrane = function(prototype) { | ||
try { | ||
var membrane = Object.create(prototype); | ||
for (var key in prototype) { | ||
if (unmountedPropertyWhitelist.hasOwnProperty(key)) { | ||
continue; | ||
} | ||
var membrane = {}; | ||
var key; | ||
for (key in prototype) { | ||
defineMembraneProperty(membrane, prototype, key); | ||
} | ||
// These are properties that goes into the instance but not the prototype. | ||
// We can create the membrane on the prototype even though this will | ||
// result in a faulty hasOwnProperty check it's better perf. | ||
for (key in componentInstanceProperties) { | ||
if (componentInstanceProperties.hasOwnProperty(key) && | ||
!(key in prototype)) { | ||
defineMembraneProperty(membrane, prototype, key); | ||
} | ||
} | ||
return membrane; | ||
}; | ||
membrane.mountComponent = function() { | ||
this.__hasBeenMounted = true; | ||
return prototype.mountComponent.apply(this, arguments); | ||
/** | ||
* Creates a membrane constructor which wraps the component that gets mounted. | ||
* | ||
* @param {function} constructor Original constructor. | ||
* @return {function} The membrane constructor. | ||
* @private | ||
*/ | ||
var createDescriptorProxy = function(constructor) { | ||
try { | ||
var ProxyConstructor = function() { | ||
this.__realComponentInstance = new constructor(); | ||
// We can only safely pass through known instance variables. Unknown | ||
// expandos are not safe. Use the real mounted instance to avoid this | ||
// problem if it blows something up. | ||
Object.freeze(this); | ||
}; | ||
return membrane; | ||
ProxyConstructor.prototype = createMountWarningMembrane( | ||
constructor.prototype | ||
); | ||
return ProxyConstructor; | ||
} catch(x) { | ||
// In IE8 define property will fail on non-DOM objects. If anything in | ||
// the membrane creation fails, we'll bail out and just use the prototype | ||
// without warnings. | ||
return prototype; | ||
// the membrane creation fails, we'll bail out and just use the plain | ||
// constructor without warnings. | ||
return constructor; | ||
} | ||
@@ -775,2 +866,3 @@ }; | ||
ReactComponent.Mixin.construct.apply(this, arguments); | ||
ReactOwner.Mixin.construct.apply(this, arguments); | ||
@@ -780,6 +872,11 @@ this.state = null; | ||
this.context = this._processContext(ReactContext.current); | ||
this.context = null; | ||
this._currentContext = ReactContext.current; | ||
this._pendingContext = null; | ||
// The descriptor that was used to instantiate this component. Will be | ||
// set by the instantiator instead of the constructor since this | ||
// constructor is currently used by both instances and descriptors. | ||
this._descriptor = null; | ||
this._compositeLifeCycleState = null; | ||
@@ -789,2 +886,13 @@ }, | ||
/** | ||
* Components in the intermediate state now has cyclic references. To avoid | ||
* breaking JSON serialization we expose a custom JSON format. | ||
* @return {object} JSON compatible representation. | ||
* @internal | ||
* @final | ||
*/ | ||
toJSON: function() { | ||
return { type: this.type, props: this.props }; | ||
}, | ||
/** | ||
* Checks whether or not this composite component is mounted. | ||
@@ -804,3 +912,3 @@ * @return {boolean} True if mounted, false otherwise. | ||
* @param {string} rootID DOM ID of the root node. | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @param {number} mountDepth number of components in the owner hierarchy | ||
@@ -823,2 +931,3 @@ * @return {?string} Rendered markup to be inserted into the DOM. | ||
this.context = this._processContext(this._currentContext); | ||
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null; | ||
@@ -851,3 +960,5 @@ this.props = this._processProps(this.props); | ||
this._renderedComponent = this._renderValidatedComponent(); | ||
this._renderedComponent = instantiateReactComponent( | ||
this._renderValidatedComponent() | ||
); | ||
@@ -888,6 +999,2 @@ // Done with mounting, `setState` will now trigger UI changes. | ||
if (this.refs) { | ||
this.refs = null; | ||
} | ||
// Some existing components rely on this.props even after they've been | ||
@@ -922,8 +1029,7 @@ // destroyed (in event handlers). | ||
if ("production" !== process.env.NODE_ENV) { | ||
if (partialState == null) { | ||
console.warn( | ||
'setState(...): You passed an undefined or null state object; ' + | ||
'instead, use forceUpdate().' | ||
); | ||
} | ||
("production" !== process.env.NODE_ENV ? warning( | ||
partialState != null, | ||
'setState(...): You passed an undefined or null state object; ' + | ||
'instead, use forceUpdate().' | ||
) : null); | ||
} | ||
@@ -1192,3 +1298,3 @@ // Merge with `_pendingState` if it exists, otherwise with existing state. | ||
receiveComponent: function(nextComponent, transaction) { | ||
if (nextComponent === this) { | ||
if (nextComponent === this._descriptor) { | ||
// Since props and context are immutable after the component is | ||
@@ -1200,2 +1306,5 @@ // mounted, we can do a cheap identity compare here to determine | ||
// Update the descriptor that was last used by this component instance | ||
this._descriptor = nextComponent; | ||
this._pendingContext = nextComponent._currentContext; | ||
@@ -1233,13 +1342,15 @@ ReactComponent.Mixin.receiveComponent.call( | ||
); | ||
var prevComponent = this._renderedComponent; | ||
var prevComponentInstance = this._renderedComponent; | ||
var nextComponent = this._renderValidatedComponent(); | ||
if (shouldUpdateReactComponent(prevComponent, nextComponent)) { | ||
prevComponent.receiveComponent(nextComponent, transaction); | ||
if (shouldUpdateReactComponent(prevComponentInstance, nextComponent)) { | ||
prevComponentInstance.receiveComponent(nextComponent, transaction); | ||
} else { | ||
// These two IDs are actually the same! But nothing should rely on that. | ||
var thisID = this._rootNodeID; | ||
var prevComponentID = prevComponent._rootNodeID; | ||
prevComponent.unmountComponent(); | ||
this._renderedComponent = nextComponent; | ||
var nextMarkup = nextComponent.mountComponent( | ||
var prevComponentID = prevComponentInstance._rootNodeID; | ||
prevComponentInstance.unmountComponent(); | ||
this._renderedComponent = instantiateReactComponent(nextComponent); | ||
var nextMarkup = this._renderedComponent.mountComponent( | ||
thisID, | ||
@@ -1356,2 +1467,3 @@ transaction, | ||
if (newThis !== component && newThis !== null) { | ||
monitorCodeUse('react_bind_warning', { component: componentName }); | ||
console.warn( | ||
@@ -1362,2 +1474,3 @@ 'bind(): React component methods may only be bound to the ' + | ||
} else if (!args.length) { | ||
monitorCodeUse('react_bind_warning', { component: componentName }); | ||
console.warn( | ||
@@ -1425,6 +1538,8 @@ 'bind(): You are binding a component method to the component. ' + | ||
var DescriptorConstructor = Constructor; | ||
var ConvenienceConstructor = function(props, children) { | ||
var instance = new Constructor(); | ||
instance.construct.apply(instance, arguments); | ||
return instance; | ||
var descriptor = new DescriptorConstructor(); | ||
descriptor.construct.apply(descriptor, arguments); | ||
return descriptor; | ||
}; | ||
@@ -1435,2 +1550,6 @@ ConvenienceConstructor.componentConstructor = Constructor; | ||
injectedMixins.forEach( | ||
mixSpecIntoComponent.bind(null, ConvenienceConstructor) | ||
); | ||
mixSpecIntoComponent(ConvenienceConstructor, spec); | ||
@@ -1445,2 +1564,6 @@ | ||
if (Constructor.prototype.componentShouldUpdate) { | ||
monitorCodeUse( | ||
'react_component_should_update_warning', | ||
{ component: spec.displayName } | ||
); | ||
console.warn( | ||
@@ -1471,3 +1594,6 @@ (spec.displayName || 'A component') + ' has a method called ' + | ||
if ("production" !== process.env.NODE_ENV) { | ||
Constructor.prototype = createMountWarningMembrane(Constructor.prototype); | ||
// In DEV the convenience constructor generates a proxy to another | ||
// instance around it to warn about access to properties on the | ||
// descriptor. | ||
DescriptorConstructor = createDescriptorProxy(Constructor); | ||
} | ||
@@ -1478,5 +1604,11 @@ | ||
isValidClass: isValidClass | ||
isValidClass: isValidClass, | ||
injection: { | ||
injectMixin: function(mixin) { | ||
injectedMixins.push(mixin); | ||
} | ||
} | ||
}; | ||
module.exports = ReactCompositeComponent; |
@@ -18,3 +18,2 @@ /** | ||
* @providesModule ReactCSSTransitionGroup | ||
* @jsx React.DOM | ||
*/ | ||
@@ -29,3 +28,3 @@ | ||
var ReactCSSTransitionGroup = React.createClass({displayName: 'ReactCSSTransitionGroup', | ||
var ReactCSSTransitionGroup = React.createClass({ | ||
propTypes: { | ||
@@ -48,9 +47,9 @@ transitionName: React.PropTypes.string.isRequired, | ||
// leave while it is leaving. | ||
return ( | ||
ReactCSSTransitionGroupChild( | ||
{name:this.props.transitionName, | ||
enter:this.props.transitionEnter, | ||
leave:this.props.transitionLeave}, | ||
child | ||
) | ||
return ReactCSSTransitionGroupChild( | ||
{ | ||
name: this.props.transitionName, | ||
enter: this.props.transitionEnter, | ||
leave: this.props.transitionLeave | ||
}, | ||
child | ||
); | ||
@@ -61,3 +60,4 @@ }, | ||
return this.transferPropsTo( | ||
ReactTransitionGroup( {childFactory:this._wrapChild}, | ||
ReactTransitionGroup( | ||
{childFactory: this._wrapChild}, | ||
this.props.children | ||
@@ -64,0 +64,0 @@ ) |
@@ -33,2 +33,5 @@ /** | ||
var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactComponentBrowserEnvironment = | ||
require("./ReactComponentBrowserEnvironment"); | ||
var ReactEventTopLevelCallback = require("./ReactEventTopLevelCallback"); | ||
@@ -93,2 +96,7 @@ var ReactDOM = require("./ReactDOM"); | ||
// This needs to happen after createFullPageComponent() otherwise the mixin | ||
// gets double injected. | ||
ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin); | ||
ReactInjection.DOMProperty.injectDOMPropertyConfig(DefaultDOMPropertyConfig); | ||
@@ -106,2 +114,4 @@ | ||
ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment); | ||
if ("production" !== process.env.NODE_ENV) { | ||
@@ -108,0 +118,0 @@ var url = (ExecutionEnvironment.canUseDOM && window.location.href) || ''; |
@@ -75,3 +75,3 @@ /** | ||
address: false, | ||
area: false, | ||
area: true, | ||
article: false, | ||
@@ -81,3 +81,3 @@ aside: false, | ||
b: false, | ||
base: false, | ||
base: true, | ||
bdi: false, | ||
@@ -132,3 +132,3 @@ bdo: false, | ||
li: false, | ||
link: false, | ||
link: true, | ||
main: false, | ||
@@ -162,3 +162,3 @@ map: false, | ||
small: false, | ||
source: false, | ||
source: true, | ||
span: false, | ||
@@ -185,3 +185,3 @@ strong: false, | ||
video: false, | ||
wbr: false, | ||
wbr: true, | ||
@@ -188,0 +188,0 @@ // SVG |
@@ -22,2 +22,3 @@ /** | ||
var AutoFocusMixin = require("./AutoFocusMixin"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -51,3 +52,3 @@ var ReactDOM = require("./ReactDOM"); | ||
mixins: [AutoFocusMixin], | ||
mixins: [AutoFocusMixin, ReactBrowserComponentMixin], | ||
@@ -54,0 +55,0 @@ render: function() { |
@@ -25,2 +25,3 @@ /** | ||
var DOMPropertyOperations = require("./DOMPropertyOperations"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactComponent = require("./ReactComponent"); | ||
@@ -103,3 +104,3 @@ var ReactEventEmitter = require("./ReactEventEmitter"); | ||
* @param {string} rootID The root DOM ID for this node. | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @param {number} mountDepth number of components in the owner hierarchy | ||
@@ -136,3 +137,3 @@ * @return {string} The computed markup. | ||
* @private | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @return {string} Markup of opening tag. | ||
@@ -169,4 +170,10 @@ */ | ||
var idMarkup = DOMPropertyOperations.createMarkupForID(this._rootNodeID); | ||
return ret + ' ' + idMarkup + '>'; | ||
// For static pages, no need to put React ID and checksum. Saves lots of | ||
// bytes. | ||
if (transaction.renderToStaticMarkup) { | ||
return ret + '>'; | ||
} | ||
var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID); | ||
return ret + ' ' + markupForID + '>'; | ||
}, | ||
@@ -178,3 +185,3 @@ | ||
* @private | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @return {string} Content markup. | ||
@@ -207,2 +214,11 @@ */ | ||
receiveComponent: function(nextComponent, transaction) { | ||
if (nextComponent === this) { | ||
// Since props and context are immutable after the component is | ||
// mounted, we can do a cheap identity compare here to determine | ||
// if this is a superfluous reconcile. | ||
// TODO: compare the descriptor | ||
return; | ||
} | ||
assertValidProps(nextComponent.props); | ||
@@ -404,3 +420,4 @@ ReactComponent.Mixin.receiveComponent.call( | ||
mixInto(ReactDOMComponent, ReactMultiChild.Mixin); | ||
mixInto(ReactDOMComponent, ReactBrowserComponentMixin); | ||
module.exports = ReactDOMComponent; |
@@ -21,2 +21,3 @@ /** | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -39,2 +40,4 @@ var ReactDOM = require("./ReactDOM"); | ||
mixins: [ReactBrowserComponentMixin], | ||
render: function() { | ||
@@ -41,0 +44,0 @@ // TODO: Instead of using `ReactDOM` directly, we should use JSX. However, |
@@ -21,2 +21,3 @@ /** | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -40,2 +41,4 @@ var ReactDOM = require("./ReactDOM"); | ||
mixins: [ReactBrowserComponentMixin], | ||
render: function() { | ||
@@ -42,0 +45,0 @@ return img(this.props); |
@@ -24,2 +24,3 @@ /** | ||
var LinkedValueUtils = require("./LinkedValueUtils"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -56,3 +57,3 @@ var ReactDOM = require("./ReactDOM"); | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin], | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], | ||
@@ -59,0 +60,0 @@ getInitialState: function() { |
@@ -21,5 +21,8 @@ /** | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
var ReactDOM = require("./ReactDOM"); | ||
var warning = require("./warning"); | ||
// Store a reference to the <option> `ReactDOMComponent`. | ||
@@ -34,11 +37,12 @@ var option = ReactDOM.option; | ||
mixins: [ReactBrowserComponentMixin], | ||
componentWillMount: function() { | ||
// TODO (yungsters): Remove support for `selected` in <option>. | ||
if (this.props.selected != null) { | ||
if ("production" !== process.env.NODE_ENV) { | ||
console.warn( | ||
'Use the `defaultValue` or `value` props on <select> instead of ' + | ||
'setting `selected` on <option>.' | ||
); | ||
} | ||
if ("production" !== process.env.NODE_ENV) { | ||
("production" !== process.env.NODE_ENV ? warning( | ||
this.props.selected == null, | ||
'Use the `defaultValue` or `value` props on <select> instead of ' + | ||
'setting `selected` on <option>.' | ||
) : null); | ||
} | ||
@@ -45,0 +49,0 @@ }, |
@@ -23,2 +23,3 @@ /** | ||
var LinkedValueUtils = require("./LinkedValueUtils"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -107,3 +108,3 @@ var ReactDOM = require("./ReactDOM"); | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin], | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], | ||
@@ -110,0 +111,0 @@ propTypes: { |
@@ -24,2 +24,3 @@ /** | ||
var LinkedValueUtils = require("./LinkedValueUtils"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
@@ -31,2 +32,4 @@ var ReactDOM = require("./ReactDOM"); | ||
var warning = require("./warning"); | ||
// Store a reference to the <textarea> `ReactDOMComponent`. | ||
@@ -53,3 +56,3 @@ var textarea = ReactDOM.textarea; | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin], | ||
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], | ||
@@ -62,6 +65,7 @@ getInitialState: function() { | ||
if ("production" !== process.env.NODE_ENV) { | ||
console.warn( | ||
("production" !== process.env.NODE_ENV ? warning( | ||
false, | ||
'Use the `defaultValue` or `value` props instead of setting ' + | ||
'children on <textarea>.' | ||
); | ||
) : null); | ||
} | ||
@@ -68,0 +72,0 @@ ("production" !== process.env.NODE_ENV ? invariant( |
@@ -23,2 +23,4 @@ /** | ||
var EventPluginHub = require("./EventPluginHub"); | ||
var ReactComponent = require("./ReactComponent"); | ||
var ReactCompositeComponent = require("./ReactCompositeComponent"); | ||
var ReactDOM = require("./ReactDOM"); | ||
@@ -31,2 +33,4 @@ var ReactEventEmitter = require("./ReactEventEmitter"); | ||
var ReactInjection = { | ||
Component: ReactComponent.injection, | ||
CompositeComponent: ReactCompositeComponent.injection, | ||
DOMProperty: DOMProperty.injection, | ||
@@ -33,0 +37,0 @@ EventPluginHub: EventPluginHub.injection, |
@@ -24,2 +24,3 @@ /** | ||
var containsNode = require("./containsNode"); | ||
var focusNode = require("./focusNode"); | ||
var getActiveElement = require("./getActiveElement"); | ||
@@ -75,3 +76,3 @@ | ||
} | ||
priorFocusedElem.focus(); | ||
focusNode(priorFocusedElem); | ||
} | ||
@@ -78,0 +79,0 @@ }, |
@@ -28,2 +28,3 @@ /** | ||
var getReactRootElementInContainer = require("./getReactRootElementInContainer"); | ||
var instantiateReactComponent = require("./instantiateReactComponent"); | ||
var invariant = require("./invariant"); | ||
@@ -303,4 +304,9 @@ var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); | ||
shouldReuseMarkup) { | ||
var reactRootID = ReactMount._registerComponent(nextComponent, container); | ||
nextComponent.mountComponentIntoNode( | ||
var componentInstance = instantiateReactComponent(nextComponent); | ||
var reactRootID = ReactMount._registerComponent( | ||
componentInstance, | ||
container | ||
); | ||
componentInstance.mountComponentIntoNode( | ||
reactRootID, | ||
@@ -317,3 +323,3 @@ container, | ||
return nextComponent; | ||
return componentInstance; | ||
} | ||
@@ -621,4 +627,6 @@ ), | ||
'findComponentRoot(..., %s): Unable to find element. This probably ' + | ||
'means the DOM was unexpectedly mutated (e.g., by the browser). ' + | ||
'Try inspecting the child nodes of the element with React ID `%s`.', | ||
'means the DOM was unexpectedly mutated (e.g., by the browser), ' + | ||
'usually due to forgetting a <tbody> when using tables or nesting <p> ' + | ||
'or <a> tags. Try inspecting the child nodes of the element with React ' + | ||
'ID `%s`.', | ||
targetID, | ||
@@ -625,0 +633,0 @@ ReactMount.getID(ancestorNode) |
@@ -26,2 +26,3 @@ /** | ||
var flattenChildren = require("./flattenChildren"); | ||
var instantiateReactComponent = require("./instantiateReactComponent"); | ||
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); | ||
@@ -196,5 +197,9 @@ | ||
if (children.hasOwnProperty(name)) { | ||
// The rendered children must be turned into instances as they're | ||
// mounted. | ||
var childInstance = instantiateReactComponent(child); | ||
children[name] = childInstance; | ||
// Inlined for performance, see `ReactInstanceHandles.createReactID`. | ||
var rootID = this._rootNodeID + name; | ||
var mountImage = child.mountComponent( | ||
var mountImage = childInstance.mountComponent( | ||
rootID, | ||
@@ -204,3 +209,3 @@ transaction, | ||
); | ||
child._mountIndex = index; | ||
childInstance._mountIndex = index; | ||
mountImages.push(mountImage); | ||
@@ -299,4 +304,6 @@ index++; | ||
} | ||
// The child must be instantiated before it's mounted. | ||
var nextChildInstance = instantiateReactComponent(nextChild); | ||
this._mountChildByNameAtIndex( | ||
nextChild, name, nextIndex, transaction | ||
nextChildInstance, name, nextIndex, transaction | ||
); | ||
@@ -303,0 +310,0 @@ } |
@@ -21,2 +21,3 @@ /** | ||
var emptyObject = require("./emptyObject"); | ||
var invariant = require("./invariant"); | ||
@@ -122,2 +123,6 @@ | ||
construct: function() { | ||
this.refs = emptyObject; | ||
}, | ||
/** | ||
@@ -137,3 +142,3 @@ * Lazily allocates the refs object and stores `component` as `ref`. | ||
) : invariant(component.isOwnedBy(this))); | ||
var refs = this.refs || (this.refs = {}); | ||
var refs = this.refs === emptyObject ? (this.refs = {}) : this.refs; | ||
refs[ref] = component; | ||
@@ -140,0 +145,0 @@ }, |
@@ -98,3 +98,3 @@ /** | ||
if (transferStrategy) { | ||
if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) { | ||
transferStrategy(props, thisKey, newProps[thisKey]); | ||
@@ -101,0 +101,0 @@ } else if (!props.hasOwnProperty(thisKey)) { |
@@ -22,3 +22,2 @@ /** | ||
var ExecutionEnvironment = require("./ExecutionEnvironment"); | ||
var PooledClass = require("./PooledClass"); | ||
@@ -131,2 +130,8 @@ var ReactEventEmitter = require("./ReactEventEmitter"); | ||
this.reinitializeTransaction(); | ||
// Only server-side rendering really needs this option (see | ||
// `ReactServerRendering`), but server-side uses | ||
// `ReactServerRenderingTransaction` instead. This option is here so that it's | ||
// accessible and defaults to false when `ReactDOMComponent` and | ||
// `ReactTextComponent` checks it in `mountComponent`.` | ||
this.renderToStaticMarkup = false; | ||
this.reactMountReady = ReactMountReady.getPooled(null); | ||
@@ -145,7 +150,3 @@ this.putListenerQueue = ReactPutListenerQueue.getPooled(); | ||
getTransactionWrappers: function() { | ||
if (ExecutionEnvironment.canUseDOM) { | ||
return TRANSACTION_WRAPPERS; | ||
} else { | ||
return []; | ||
} | ||
return TRANSACTION_WRAPPERS; | ||
}, | ||
@@ -152,0 +153,0 @@ |
@@ -24,4 +24,6 @@ /** | ||
var ReactMarkupChecksum = require("./ReactMarkupChecksum"); | ||
var ReactReconcileTransaction = require("./ReactReconcileTransaction"); | ||
var ReactServerRenderingTransaction = | ||
require("./ReactServerRenderingTransaction"); | ||
var instantiateReactComponent = require("./instantiateReactComponent"); | ||
var invariant = require("./invariant"); | ||
@@ -31,3 +33,3 @@ | ||
* @param {ReactComponent} component | ||
* @return {string} the markup | ||
* @return {string} the HTML markup | ||
*/ | ||
@@ -46,17 +48,45 @@ function renderComponentToString(component) { | ||
var id = ReactInstanceHandles.createReactRootID(); | ||
var transaction = ReactReconcileTransaction.getPooled(); | ||
transaction.reinitializeTransaction(); | ||
var transaction; | ||
try { | ||
var id = ReactInstanceHandles.createReactRootID(); | ||
transaction = ReactServerRenderingTransaction.getPooled(false); | ||
return transaction.perform(function() { | ||
var markup = component.mountComponent(id, transaction, 0); | ||
var componentInstance = instantiateReactComponent(component); | ||
var markup = componentInstance.mountComponent(id, transaction, 0); | ||
return ReactMarkupChecksum.addChecksumToMarkup(markup); | ||
}, null); | ||
} finally { | ||
ReactReconcileTransaction.release(transaction); | ||
ReactServerRenderingTransaction.release(transaction); | ||
} | ||
} | ||
/** | ||
* @param {ReactComponent} component | ||
* @return {string} the HTML markup, without the extra React ID and checksum | ||
* (for generating static pages) | ||
*/ | ||
function renderComponentToStaticMarkup(component) { | ||
("production" !== process.env.NODE_ENV ? invariant( | ||
ReactComponent.isValidComponent(component), | ||
'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.' | ||
) : invariant(ReactComponent.isValidComponent(component))); | ||
var transaction; | ||
try { | ||
var id = ReactInstanceHandles.createReactRootID(); | ||
transaction = ReactServerRenderingTransaction.getPooled(true); | ||
return transaction.perform(function() { | ||
var componentInstance = instantiateReactComponent(component); | ||
return componentInstance.mountComponent(id, transaction, 0); | ||
}, null); | ||
} finally { | ||
ReactServerRenderingTransaction.release(transaction); | ||
} | ||
} | ||
module.exports = { | ||
renderComponentToString: renderComponentToString | ||
renderComponentToString: renderComponentToString, | ||
renderComponentToStaticMarkup: renderComponentToStaticMarkup | ||
}; |
@@ -23,2 +23,3 @@ /** | ||
var DOMPropertyOperations = require("./DOMPropertyOperations"); | ||
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); | ||
var ReactComponent = require("./ReactComponent"); | ||
@@ -48,3 +49,14 @@ | ||
/** | ||
* Used to clone the text descriptor object before it's mounted. | ||
* | ||
* @param {object} props | ||
* @return {object} A new ReactTextComponent instance | ||
*/ | ||
ReactTextComponent.ConvenienceConstructor = function(props) { | ||
return new ReactTextComponent(props.text); | ||
}; | ||
mixInto(ReactTextComponent, ReactComponent.Mixin); | ||
mixInto(ReactTextComponent, ReactBrowserComponentMixin); | ||
mixInto(ReactTextComponent, { | ||
@@ -57,3 +69,3 @@ | ||
* @param {string} rootID DOM ID of the root node. | ||
* @param {ReactReconcileTransaction} transaction | ||
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction | ||
* @param {number} mountDepth number of components in the owner hierarchy | ||
@@ -70,5 +82,15 @@ * @return {string} Markup for this text node. | ||
); | ||
var escapedText = escapeTextForBrowser(this.props.text); | ||
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) + '>' + | ||
escapeTextForBrowser(this.props.text) + | ||
escapedText + | ||
'</span>' | ||
@@ -75,0 +97,0 @@ ); |
@@ -36,2 +36,3 @@ /** | ||
var cloneWithProps = require("./cloneWithProps"); | ||
var update = require("./update"); | ||
@@ -44,3 +45,4 @@ React.addons = { | ||
classSet: cx, | ||
cloneWithProps: cloneWithProps | ||
cloneWithProps: cloneWithProps, | ||
update: update | ||
}; | ||
@@ -47,0 +49,0 @@ |
@@ -23,22 +23,25 @@ /** | ||
/** | ||
* Given a `prevComponent` and `nextComponent`, determines if `prevComponent` | ||
* should be updated as opposed to being destroyed or replaced. | ||
* Given a `prevComponentInstance` and `nextComponent`, determines if | ||
* `prevComponentInstance` should be updated as opposed to being destroyed or | ||
* replaced by a new instance. The second argument is a descriptor. Future | ||
* versions of the reconciler should only compare descriptors to other | ||
* descriptors. | ||
* | ||
* @param {?object} prevComponent | ||
* @param {?object} nextComponent | ||
* @return {boolean} True if `prevComponent` should be updated. | ||
* @param {?object} prevComponentInstance | ||
* @param {?object} nextDescriptor | ||
* @return {boolean} True if `prevComponentInstance` should be updated. | ||
* @protected | ||
*/ | ||
function shouldUpdateReactComponent(prevComponent, nextComponent) { | ||
function shouldUpdateReactComponent(prevComponentInstance, nextDescriptor) { | ||
// TODO: Remove warning after a release. | ||
if (prevComponent && nextComponent && | ||
prevComponent.constructor === nextComponent.constructor && ( | ||
(prevComponent.props && prevComponent.props.key) === | ||
(nextComponent.props && nextComponent.props.key) | ||
if (prevComponentInstance && nextDescriptor && | ||
prevComponentInstance.constructor === nextDescriptor.constructor && ( | ||
(prevComponentInstance.props && prevComponentInstance.props.key) === | ||
(nextDescriptor.props && nextDescriptor.props.key) | ||
)) { | ||
if (prevComponent._owner === nextComponent._owner) { | ||
if (prevComponentInstance._owner === nextDescriptor._owner) { | ||
return true; | ||
} else { | ||
if ("production" !== process.env.NODE_ENV) { | ||
if (prevComponent.state) { | ||
if (prevComponentInstance.state) { | ||
console.warn( | ||
@@ -49,4 +52,4 @@ 'A recent change to React has been found to impact your code. ' + | ||
'Previously, ownership was not considered when updating.', | ||
prevComponent, | ||
nextComponent | ||
prevComponentInstance, | ||
nextDescriptor | ||
); | ||
@@ -53,0 +56,0 @@ } |
@@ -129,3 +129,4 @@ /** | ||
subtreeCount = 1; | ||
} else if (children.mountComponentIntoNode) { | ||
} else if (children.type && children.type.prototype && | ||
children.type.prototype.mountComponentIntoNode) { | ||
callback(traverseContext, children, storageName, indexSoFar); | ||
@@ -132,0 +133,0 @@ subtreeCount = 1; |
{ | ||
"name": "react", | ||
"description": "React is a JavaScript library for building user interfaces.", | ||
"version": "0.9.0", | ||
"version": "0.10.0-rc1", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "react" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
588579
152
16713
188