UNPKG

25.5 kBJavaScriptView Raw
1/**
2 * Copyright 2013-present, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 *
9 */
10
11'use strict';
12
13var _prodInvariant = require('./reactProdInvariant');
14
15var DOMLazyTree = require('./DOMLazyTree');
16var DOMProperty = require('./DOMProperty');
17var React = require('react/lib/React');
18var ReactBrowserEventEmitter = require('./ReactBrowserEventEmitter');
19var ReactCurrentOwner = require('react/lib/ReactCurrentOwner');
20var ReactDOMComponentTree = require('./ReactDOMComponentTree');
21var ReactDOMContainerInfo = require('./ReactDOMContainerInfo');
22var ReactDOMFeatureFlags = require('./ReactDOMFeatureFlags');
23var ReactFeatureFlags = require('./ReactFeatureFlags');
24var ReactInstanceMap = require('./ReactInstanceMap');
25var ReactInstrumentation = require('./ReactInstrumentation');
26var ReactMarkupChecksum = require('./ReactMarkupChecksum');
27var ReactReconciler = require('./ReactReconciler');
28var ReactUpdateQueue = require('./ReactUpdateQueue');
29var ReactUpdates = require('./ReactUpdates');
30
31var emptyObject = require('fbjs/lib/emptyObject');
32var instantiateReactComponent = require('./instantiateReactComponent');
33var invariant = require('fbjs/lib/invariant');
34var setInnerHTML = require('./setInnerHTML');
35var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');
36var warning = require('fbjs/lib/warning');
37
38var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
39var ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;
40
41var ELEMENT_NODE_TYPE = 1;
42var DOC_NODE_TYPE = 9;
43var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
44
45var instancesByReactRootID = {};
46
47/**
48 * Finds the index of the first character
49 * that's not common between the two given strings.
50 *
51 * @return {number} the index of the character where the strings diverge
52 */
53function firstDifferenceIndex(string1, string2) {
54 var minLen = Math.min(string1.length, string2.length);
55 for (var i = 0; i < minLen; i++) {
56 if (string1.charAt(i) !== string2.charAt(i)) {
57 return i;
58 }
59 }
60 return string1.length === string2.length ? -1 : minLen;
61}
62
63/**
64 * @param {DOMElement|DOMDocument} container DOM element that may contain
65 * a React component
66 * @return {?*} DOM element that may have the reactRoot ID, or null.
67 */
68function getReactRootElementInContainer(container) {
69 if (!container) {
70 return null;
71 }
72
73 if (container.nodeType === DOC_NODE_TYPE) {
74 return container.documentElement;
75 } else {
76 return container.firstChild;
77 }
78}
79
80function internalGetID(node) {
81 // If node is something like a window, document, or text node, none of
82 // which support attributes or a .getAttribute method, gracefully return
83 // the empty string, as if the attribute were missing.
84 return node.getAttribute && node.getAttribute(ATTR_NAME) || '';
85}
86
87/**
88 * Mounts this component and inserts it into the DOM.
89 *
90 * @param {ReactComponent} componentInstance The instance to mount.
91 * @param {DOMElement} container DOM element to mount into.
92 * @param {ReactReconcileTransaction} transaction
93 * @param {boolean} shouldReuseMarkup If true, do not insert markup
94 */
95function mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {
96 var markerName;
97 if (ReactFeatureFlags.logTopLevelRenders) {
98 var wrappedElement = wrapperInstance._currentElement.props.child;
99 var type = wrappedElement.type;
100 markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);
101 console.time(markerName);
102 }
103
104 var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context, 0 /* parentDebugID */
105 );
106
107 if (markerName) {
108 console.timeEnd(markerName);
109 }
110
111 wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
112 ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);
113}
114
115/**
116 * Batched mount.
117 *
118 * @param {ReactComponent} componentInstance The instance to mount.
119 * @param {DOMElement} container DOM element to mount into.
120 * @param {boolean} shouldReuseMarkup If true, do not insert markup
121 */
122function batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {
123 var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
124 /* useCreateElement */
125 !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);
126 transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);
127 ReactUpdates.ReactReconcileTransaction.release(transaction);
128}
129
130/**
131 * Unmounts a component and removes it from the DOM.
132 *
133 * @param {ReactComponent} instance React component instance.
134 * @param {DOMElement} container DOM element to unmount from.
135 * @final
136 * @internal
137 * @see {ReactMount.unmountComponentAtNode}
138 */
139function unmountComponentFromNode(instance, container, safely) {
140 if (process.env.NODE_ENV !== 'production') {
141 ReactInstrumentation.debugTool.onBeginFlush();
142 }
143 ReactReconciler.unmountComponent(instance, safely);
144 if (process.env.NODE_ENV !== 'production') {
145 ReactInstrumentation.debugTool.onEndFlush();
146 }
147
148 if (container.nodeType === DOC_NODE_TYPE) {
149 container = container.documentElement;
150 }
151
152 // http://jsperf.com/emptying-a-node
153 while (container.lastChild) {
154 container.removeChild(container.lastChild);
155 }
156}
157
158/**
159 * True if the supplied DOM node has a direct React-rendered child that is
160 * not a React root element. Useful for warning in `render`,
161 * `unmountComponentAtNode`, etc.
162 *
163 * @param {?DOMElement} node The candidate DOM node.
164 * @return {boolean} True if the DOM element contains a direct child that was
165 * rendered by React but is not a root element.
166 * @internal
167 */
168function hasNonRootReactChild(container) {
169 var rootEl = getReactRootElementInContainer(container);
170 if (rootEl) {
171 var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);
172 return !!(inst && inst._hostParent);
173 }
174}
175
176/**
177 * True if the supplied DOM node is a React DOM element and
178 * it has been rendered by another copy of React.
179 *
180 * @param {?DOMElement} node The candidate DOM node.
181 * @return {boolean} True if the DOM has been rendered by another copy of React
182 * @internal
183 */
184function nodeIsRenderedByOtherInstance(container) {
185 var rootEl = getReactRootElementInContainer(container);
186 return !!(rootEl && isReactNode(rootEl) && !ReactDOMComponentTree.getInstanceFromNode(rootEl));
187}
188
189/**
190 * True if the supplied DOM node is a valid node element.
191 *
192 * @param {?DOMElement} node The candidate DOM node.
193 * @return {boolean} True if the DOM is a valid DOM node.
194 * @internal
195 */
196function isValidContainer(node) {
197 return !!(node && (node.nodeType === ELEMENT_NODE_TYPE || node.nodeType === DOC_NODE_TYPE || node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE));
198}
199
200/**
201 * True if the supplied DOM node is a valid React node element.
202 *
203 * @param {?DOMElement} node The candidate DOM node.
204 * @return {boolean} True if the DOM is a valid React DOM node.
205 * @internal
206 */
207function isReactNode(node) {
208 return isValidContainer(node) && (node.hasAttribute(ROOT_ATTR_NAME) || node.hasAttribute(ATTR_NAME));
209}
210
211function getHostRootInstanceInContainer(container) {
212 var rootEl = getReactRootElementInContainer(container);
213 var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);
214 return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;
215}
216
217function getTopLevelWrapperInContainer(container) {
218 var root = getHostRootInstanceInContainer(container);
219 return root ? root._hostContainerInfo._topLevelWrapper : null;
220}
221
222/**
223 * Temporary (?) hack so that we can store all top-level pending updates on
224 * composites instead of having to worry about different types of components
225 * here.
226 */
227var topLevelRootCounter = 1;
228var TopLevelWrapper = function () {
229 this.rootID = topLevelRootCounter++;
230};
231TopLevelWrapper.prototype.isReactComponent = {};
232if (process.env.NODE_ENV !== 'production') {
233 TopLevelWrapper.displayName = 'TopLevelWrapper';
234}
235TopLevelWrapper.prototype.render = function () {
236 return this.props.child;
237};
238TopLevelWrapper.isReactTopLevelWrapper = true;
239
240/**
241 * Mounting is the process of initializing a React component by creating its
242 * representative DOM elements and inserting them into a supplied `container`.
243 * Any prior content inside `container` is destroyed in the process.
244 *
245 * ReactMount.render(
246 * component,
247 * document.getElementById('container')
248 * );
249 *
250 * <div id="container"> <-- Supplied `container`.
251 * <div data-reactid=".3"> <-- Rendered reactRoot of React
252 * // ... component.
253 * </div>
254 * </div>
255 *
256 * Inside of `container`, the first element rendered is the "reactRoot".
257 */
258var ReactMount = {
259 TopLevelWrapper: TopLevelWrapper,
260
261 /**
262 * Used by devtools. The keys are not important.
263 */
264 _instancesByReactRootID: instancesByReactRootID,
265
266 /**
267 * This is a hook provided to support rendering React components while
268 * ensuring that the apparent scroll position of its `container` does not
269 * change.
270 *
271 * @param {DOMElement} container The `container` being rendered into.
272 * @param {function} renderCallback This must be called once to do the render.
273 */
274 scrollMonitor: function (container, renderCallback) {
275 renderCallback();
276 },
277
278 /**
279 * Take a component that's already mounted into the DOM and replace its props
280 * @param {ReactComponent} prevComponent component instance already in the DOM
281 * @param {ReactElement} nextElement component instance to render
282 * @param {DOMElement} container container to render into
283 * @param {?function} callback function triggered on completion
284 */
285 _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {
286 ReactMount.scrollMonitor(container, function () {
287 ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);
288 if (callback) {
289 ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
290 }
291 });
292
293 return prevComponent;
294 },
295
296 /**
297 * Render a new component into the DOM. Hooked by hooks!
298 *
299 * @param {ReactElement} nextElement element to render
300 * @param {DOMElement} container container to render into
301 * @param {boolean} shouldReuseMarkup if we should skip the markup insertion
302 * @return {ReactComponent} nextComponent
303 */
304 _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {
305 // Various parts of our code (such as ReactCompositeComponent's
306 // _renderValidatedComponent) assume that calls to render aren't nested;
307 // verify that that's the case.
308 process.env.NODE_ENV !== 'production' ? 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. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;
309
310 !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;
311
312 ReactBrowserEventEmitter.ensureScrollValueMonitoring();
313 var componentInstance = instantiateReactComponent(nextElement, false);
314
315 // The initial render is synchronous but any updates that happen during
316 // rendering, in componentWillMount or componentDidMount, will be batched
317 // according to the current batching strategy.
318
319 ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);
320
321 var wrapperID = componentInstance._instance.rootID;
322 instancesByReactRootID[wrapperID] = componentInstance;
323
324 return componentInstance;
325 },
326
327 /**
328 * Renders a React component into the DOM in the supplied `container`.
329 *
330 * If the React component was previously rendered into `container`, this will
331 * perform an update on it and only mutate the DOM as necessary to reflect the
332 * latest React component.
333 *
334 * @param {ReactComponent} parentComponent The conceptual parent of this render tree.
335 * @param {ReactElement} nextElement Component element to render.
336 * @param {DOMElement} container DOM element to render into.
337 * @param {?function} callback function triggered on completion
338 * @return {ReactComponent} Component instance rendered in `container`.
339 */
340 renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
341 !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;
342 return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);
343 },
344
345 _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
346 ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
347 !React.isValidElement(nextElement) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? " Instead of passing a string like 'div', pass " + "React.createElement('div') or <div />." : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : // Check if it quacks like an element
348 nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? " Instead of passing a string like 'div', pass " + "React.createElement('div') or <div />." : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;
349
350 process.env.NODE_ENV !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;
351
352 var nextWrappedElement = React.createElement(TopLevelWrapper, {
353 child: nextElement
354 });
355
356 var nextContext;
357 if (parentComponent) {
358 var parentInst = ReactInstanceMap.get(parentComponent);
359 nextContext = parentInst._processChildContext(parentInst._context);
360 } else {
361 nextContext = emptyObject;
362 }
363
364 var prevComponent = getTopLevelWrapperInContainer(container);
365
366 if (prevComponent) {
367 var prevWrappedElement = prevComponent._currentElement;
368 var prevElement = prevWrappedElement.props.child;
369 if (shouldUpdateReactComponent(prevElement, nextElement)) {
370 var publicInst = prevComponent._renderedComponent.getPublicInstance();
371 var updatedCallback = callback && function () {
372 callback.call(publicInst);
373 };
374 ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);
375 return publicInst;
376 } else {
377 ReactMount.unmountComponentAtNode(container);
378 }
379 }
380
381 var reactRootElement = getReactRootElementInContainer(container);
382 var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);
383 var containerHasNonRootReactChild = hasNonRootReactChild(container);
384
385 if (process.env.NODE_ENV !== 'production') {
386 process.env.NODE_ENV !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;
387
388 if (!containerHasReactMarkup || reactRootElement.nextSibling) {
389 var rootElementSibling = reactRootElement;
390 while (rootElementSibling) {
391 if (internalGetID(rootElementSibling)) {
392 process.env.NODE_ENV !== 'production' ? 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.') : void 0;
393 break;
394 }
395 rootElementSibling = rootElementSibling.nextSibling;
396 }
397 }
398 }
399
400 var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;
401 var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();
402 if (callback) {
403 callback.call(component);
404 }
405 return component;
406 },
407
408 /**
409 * Renders a React component into the DOM in the supplied `container`.
410 * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render
411 *
412 * If the React component was previously rendered into `container`, this will
413 * perform an update on it and only mutate the DOM as necessary to reflect the
414 * latest React component.
415 *
416 * @param {ReactElement} nextElement Component element to render.
417 * @param {DOMElement} container DOM element to render into.
418 * @param {?function} callback function triggered on completion
419 * @return {ReactComponent} Component instance rendered in `container`.
420 */
421 render: function (nextElement, container, callback) {
422 return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
423 },
424
425 /**
426 * Unmounts and destroys the React component rendered in the `container`.
427 * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode
428 *
429 * @param {DOMElement} container DOM element containing a React component.
430 * @return {boolean} True if a component was found in and unmounted from
431 * `container`
432 */
433 unmountComponentAtNode: function (container) {
434 // Various parts of our code (such as ReactCompositeComponent's
435 // _renderValidatedComponent) assume that calls to render aren't nested;
436 // verify that that's the case. (Strictly speaking, unmounting won't cause a
437 // render but we still don't expect to be in a render call here.)
438 process.env.NODE_ENV !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;
439
440 !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;
441
442 if (process.env.NODE_ENV !== 'production') {
443 process.env.NODE_ENV !== 'production' ? warning(!nodeIsRenderedByOtherInstance(container), "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.') : void 0;
444 }
445
446 var prevComponent = getTopLevelWrapperInContainer(container);
447 if (!prevComponent) {
448 // Check if the node being unmounted was rendered by React, but isn't a
449 // root node.
450 var containerHasNonRootReactChild = hasNonRootReactChild(container);
451
452 // Check if the container itself is a React root node.
453 var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);
454
455 if (process.env.NODE_ENV !== 'production') {
456 process.env.NODE_ENV !== 'production' ? warning(!containerHasNonRootReactChild, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;
457 }
458
459 return false;
460 }
461 delete instancesByReactRootID[prevComponent._instance.rootID];
462 ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);
463 return true;
464 },
465
466 _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {
467 !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;
468
469 if (shouldReuseMarkup) {
470 var rootElement = getReactRootElementInContainer(container);
471 if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {
472 ReactDOMComponentTree.precacheNode(instance, rootElement);
473 return;
474 } else {
475 var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
476 rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
477
478 var rootMarkup = rootElement.outerHTML;
479 rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);
480
481 var normalizedMarkup = markup;
482 if (process.env.NODE_ENV !== 'production') {
483 // because rootMarkup is retrieved from the DOM, various normalizations
484 // will have occurred which will not be present in `markup`. Here,
485 // insert markup into a <div> or <iframe> depending on the container
486 // type to perform the same normalizations before comparing.
487 var normalizer;
488 if (container.nodeType === ELEMENT_NODE_TYPE) {
489 normalizer = document.createElement('div');
490 normalizer.innerHTML = markup;
491 normalizedMarkup = normalizer.innerHTML;
492 } else {
493 normalizer = document.createElement('iframe');
494 document.body.appendChild(normalizer);
495 normalizer.contentDocument.write(markup);
496 normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;
497 document.body.removeChild(normalizer);
498 }
499 }
500
501 var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);
502 var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);
503
504 !(container.nodeType !== DOC_NODE_TYPE) ? process.env.NODE_ENV !== 'production' ? invariant(false, '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) : _prodInvariant('42', difference) : void 0;
505
506 if (process.env.NODE_ENV !== 'production') {
507 process.env.NODE_ENV !== 'production' ? 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) : void 0;
508 }
509 }
510 }
511
512 !(container.nodeType !== DOC_NODE_TYPE) ? process.env.NODE_ENV !== 'production' ? invariant(false, '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 ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;
513
514 if (transaction.useCreateElement) {
515 while (container.lastChild) {
516 container.removeChild(container.lastChild);
517 }
518 DOMLazyTree.insertTreeBefore(container, markup, null);
519 } else {
520 setInnerHTML(container, markup);
521 ReactDOMComponentTree.precacheNode(instance, container.firstChild);
522 }
523
524 if (process.env.NODE_ENV !== 'production') {
525 var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);
526 if (hostNode._debugID !== 0) {
527 ReactInstrumentation.debugTool.onHostOperation({
528 instanceID: hostNode._debugID,
529 type: 'mount',
530 payload: markup.toString()
531 });
532 }
533 }
534 }
535};
536
537module.exports = ReactMount;
\No newline at end of file