UNPKG

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