diff --git a/src/renderers/dom/client/ReactDOMIDOperations.js b/src/renderers/dom/client/ReactDOMIDOperations.js index bec8d3e619..65b01b1e67 100644 --- a/src/renderers/dom/client/ReactDOMIDOperations.js +++ b/src/renderers/dom/client/ReactDOMIDOperations.js @@ -12,7 +12,6 @@ 'use strict'; -var CSSPropertyOperations = require('CSSPropertyOperations'); var DOMChildrenOperations = require('DOMChildrenOperations'); var DOMPropertyOperations = require('DOMPropertyOperations'); var ReactMount = require('ReactMount'); @@ -33,8 +32,7 @@ var INVALID_PROPERTY_ERRORS = { }; /** - * Operations used to process updates to DOM nodes. This is made injectable via - * `ReactDOMComponent.BackendIDOperations`. + * Operations used to process updates to DOM nodes. */ var ReactDOMIDOperations = { @@ -65,67 +63,6 @@ var ReactDOMIDOperations = { } }, - /** - * Updates a DOM node with new property values. - * - * @param {string} id ID of the node to update. - * @param {string} name A valid property name. - * @param {*} value New value of the property. - * @internal - */ - updateAttributeByID: function(id, name, value) { - var node = ReactMount.getNode(id); - invariant( - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), - 'updatePropertyByID(...): %s', - INVALID_PROPERTY_ERRORS[name] - ); - DOMPropertyOperations.setValueForAttribute(node, name, value); - }, - - /** - * Updates a DOM node to remove a property. This should only be used to remove - * DOM properties in `DOMProperty`. - * - * @param {string} id ID of the node to update. - * @param {string} name A property name to remove, see `DOMProperty`. - * @internal - */ - deletePropertyByID: function(id, name, value) { - var node = ReactMount.getNode(id); - invariant( - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), - 'updatePropertyByID(...): %s', - INVALID_PROPERTY_ERRORS[name] - ); - DOMPropertyOperations.deleteValueForProperty(node, name, value); - }, - - /** - * Updates a DOM node with new style values. If a value is specified as '', - * the corresponding style property will be unset. - * - * @param {string} id ID of the node to update. - * @param {object} styles Mapping from styles to values. - * @internal - */ - updateStylesByID: function(id, styles) { - var node = ReactMount.getNode(id); - CSSPropertyOperations.setValueForStyles(node, styles); - }, - - /** - * Updates a DOM node's text content set by `props.content`. - * - * @param {string} id ID of the node to update. - * @param {string} content Text content. - * @internal - */ - updateTextContentByID: function(id, content) { - var node = ReactMount.getNode(id); - DOMChildrenOperations.updateTextContent(node, content); - }, - /** * Replaces a DOM node that exists in the document with markup. * @@ -156,9 +93,6 @@ var ReactDOMIDOperations = { ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', { updatePropertyByID: 'updatePropertyByID', - deletePropertyByID: 'deletePropertyByID', - updateStylesByID: 'updateStylesByID', - updateTextContentByID: 'updateTextContentByID', dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID', dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates', }); diff --git a/src/renderers/dom/client/ReactMount.js b/src/renderers/dom/client/ReactMount.js index c505d0dd67..0a34823e7f 100644 --- a/src/renderers/dom/client/ReactMount.js +++ b/src/renderers/dom/client/ReactMount.js @@ -14,6 +14,7 @@ var DOMProperty = require('DOMProperty'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactCurrentOwner = require('ReactCurrentOwner'); +var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); var ReactElement = require('ReactElement'); var ReactEmptyComponent = require('ReactEmptyComponent'); var ReactInstanceHandles = require('ReactInstanceHandles'); @@ -24,6 +25,7 @@ var ReactReconciler = require('ReactReconciler'); var ReactUpdateQueue = require('ReactUpdateQueue'); var ReactUpdates = require('ReactUpdates'); +var assign = require('Object.assign'); var emptyObject = require('emptyObject'); var containsNode = require('containsNode'); var instantiateReactComponent = require('instantiateReactComponent'); @@ -42,6 +44,10 @@ var ELEMENT_NODE_TYPE = 1; var DOC_NODE_TYPE = 9; var DOCUMENT_FRAGMENT_NODE_TYPE = 11; +var ownerDocumentContextKey = + '__ReactMount_ownerDocument$' + Math.random().toString(36).slice(2); + + /** Mapping from reactRootID to React component instance. */ var instancesByReactRootID = {}; @@ -264,6 +270,14 @@ function mountComponentIntoNode( shouldReuseMarkup, context ) { + if (ReactDOMFeatureFlags.useCreateElement) { + context = assign({}, context); + if (container.nodeType === DOC_NODE_TYPE) { + context[ownerDocumentContextKey] = container; + } else { + context[ownerDocumentContextKey] = container.ownerDocument; + } + } if (__DEV__) { if (context === emptyObject) { context = {}; @@ -276,7 +290,12 @@ function mountComponentIntoNode( componentInstance, rootID, transaction, context ); componentInstance._renderedComponent._topLevelWrapper = componentInstance; - ReactMount._mountImageIntoNode(markup, container, shouldReuseMarkup); + ReactMount._mountImageIntoNode( + markup, + container, + shouldReuseMarkup, + transaction + ); } /** @@ -294,7 +313,9 @@ function batchedMountComponentIntoNode( shouldReuseMarkup, context ) { - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled( + /* forceHTML */ shouldReuseMarkup + ); transaction.perform( mountComponentIntoNode, null, @@ -870,7 +891,12 @@ var ReactMount = { ); }, - _mountImageIntoNode: function(markup, container, shouldReuseMarkup) { + _mountImageIntoNode: function( + markup, + container, + shouldReuseMarkup, + transaction + ) { invariant( container && ( container.nodeType === ELEMENT_NODE_TYPE || @@ -959,9 +985,18 @@ var ReactMount = { 'See React.renderToString() for server rendering.' ); - setInnerHTML(container, markup); + if (transaction.useCreateElement) { + while (container.lastChild) { + container.removeChild(container.lastChild); + } + container.appendChild(markup); + } else { + setInnerHTML(container, markup); + } }, + ownerDocumentContextKey: ownerDocumentContextKey, + /** * React ID utilities. */ diff --git a/src/renderers/dom/client/ReactReconcileTransaction.js b/src/renderers/dom/client/ReactReconcileTransaction.js index 086f30fa7a..51b70ee179 100644 --- a/src/renderers/dom/client/ReactReconcileTransaction.js +++ b/src/renderers/dom/client/ReactReconcileTransaction.js @@ -15,6 +15,7 @@ var CallbackQueue = require('CallbackQueue'); var PooledClass = require('PooledClass'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); +var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); var ReactInputSelection = require('ReactInputSelection'); var Transaction = require('Transaction'); @@ -106,7 +107,7 @@ var TRANSACTION_WRAPPERS = [ * * @class ReactReconcileTransaction */ -function ReactReconcileTransaction() { +function ReactReconcileTransaction(forceHTML) { this.reinitializeTransaction(); // Only server-side rendering really needs this option (see // `ReactServerRendering`), but server-side uses @@ -115,6 +116,8 @@ function ReactReconcileTransaction() { // `ReactTextComponent` checks it in `mountComponent`.` this.renderToStaticMarkup = false; this.reactMountReady = CallbackQueue.getPooled(null); + this.useCreateElement = + !forceHTML && ReactDOMFeatureFlags.useCreateElement; } var Mixin = { diff --git a/src/renderers/dom/client/utils/DOMChildrenOperations.js b/src/renderers/dom/client/utils/DOMChildrenOperations.js index ad6bea4057..0d4d4003ac 100644 --- a/src/renderers/dom/client/utils/DOMChildrenOperations.js +++ b/src/renderers/dom/client/utils/DOMChildrenOperations.js @@ -98,7 +98,13 @@ var DOMChildrenOperations = { } } - var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); + var renderedMarkup; + // markupList is either a list of markup or just a list of elements + if (markupList.length && typeof markupList[0] === 'string') { + renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); + } else { + renderedMarkup = markupList; + } // Remove updated children first so that `toIndex` is consistent. if (updatedChildren) { diff --git a/src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js b/src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js index 91894b6221..c4b7c38a21 100644 --- a/src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js +++ b/src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js @@ -62,7 +62,7 @@ describe('ReactDOMTextarea', function() { }); it('should display "false" for `defaultValue` of `false`', function() { - var stub = ; + var stub = ; stub = renderTextarea(stub); var node = ReactDOM.findDOMNode(stub); @@ -76,7 +76,7 @@ describe('ReactDOMTextarea', function() { }, }; - var stub = ; + var stub = ; stub = renderTextarea(stub); var node = ReactDOM.findDOMNode(stub); diff --git a/src/renderers/dom/server/ReactServerRenderingTransaction.js b/src/renderers/dom/server/ReactServerRenderingTransaction.js index 400bbb8893..80acc0f898 100644 --- a/src/renderers/dom/server/ReactServerRenderingTransaction.js +++ b/src/renderers/dom/server/ReactServerRenderingTransaction.js @@ -51,6 +51,7 @@ function ReactServerRenderingTransaction(renderToStaticMarkup) { this.reinitializeTransaction(); this.renderToStaticMarkup = renderToStaticMarkup; this.reactMountReady = CallbackQueue.getPooled(null); + this.useCreateElement = false; } var Mixin = { diff --git a/src/renderers/dom/shared/DOMPropertyOperations.js b/src/renderers/dom/shared/DOMPropertyOperations.js index 20491d9d5b..2bf869ac39 100644 --- a/src/renderers/dom/shared/DOMPropertyOperations.js +++ b/src/renderers/dom/shared/DOMPropertyOperations.js @@ -105,6 +105,10 @@ var DOMPropertyOperations = { quoteAttributeValueForBrowser(id); }, + setAttributeForID: function(node, id) { + node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id); + }, + /** * Creates markup for a property. * diff --git a/src/renderers/dom/shared/Danger.js b/src/renderers/dom/shared/Danger.js index 63ba5fb950..d5a70cf33a 100644 --- a/src/renderers/dom/shared/Danger.js +++ b/src/renderers/dom/shared/Danger.js @@ -172,7 +172,12 @@ var Danger = { 'server rendering. See React.renderToString().' ); - var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; + var newChild; + if (typeof markup === 'string') { + newChild = createNodesFromMarkup(markup, emptyFunction)[0]; + } else { + newChild = markup; + } oldChild.parentNode.replaceChild(newChild, oldChild); }, diff --git a/src/renderers/dom/shared/ReactDOMComponent.js b/src/renderers/dom/shared/ReactDOMComponent.js index b150acab00..4301b3438e 100644 --- a/src/renderers/dom/shared/ReactDOMComponent.js +++ b/src/renderers/dom/shared/ReactDOMComponent.js @@ -37,6 +37,8 @@ var escapeTextContentForBrowser = require('escapeTextContentForBrowser'); var invariant = require('invariant'); var isEventSupported = require('isEventSupported'); var keyOf = require('keyOf'); +var setInnerHTML = require('setInnerHTML'); +var setTextContent = require('setTextContent'); var shallowEqual = require('shallowEqual'); var validateDOMNesting = require('validateDOMNesting'); var warning = require('warning'); @@ -205,12 +207,6 @@ function checkAndWarnForMutatedStyle(style1, style2, component) { ); } - -/** - * Optionally injectable operations for mutating the DOM - */ -var BackendIDOperations = null; - /** * @param {object} component * @param {?object} props @@ -561,8 +557,26 @@ ReactDOMComponent.Mixin = { } } - var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props); - var tagContent = this._createContentMarkup(transaction, props, context); + var mountImage; + if (transaction.useCreateElement) { + var ownerDocument = context[ReactMount.ownerDocumentContextKey]; + var el = ownerDocument.createElement(this._currentElement.type); + DOMPropertyOperations.setAttributeForID(el, this._rootNodeID); + // Populate node cache + ReactMount.getID(el); + this._updateDOMProperties({}, props, transaction, el); + this._createInitialChildren(transaction, props, context, el); + mountImage = el; + } else { + var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props); + var tagContent = this._createContentMarkup(transaction, props, context); + if (!tagContent && omittedCloseTags[this._tag]) { + mountImage = tagOpen + '/>'; + } else { + mountImage = + tagOpen + '>' + tagContent + '' + this._currentElement.type + '>'; + } + } switch (this._tag) { case 'button': @@ -578,10 +592,7 @@ ReactDOMComponent.Mixin = { break; } - if (!tagContent && omittedCloseTags[this._tag]) { - return tagOpen + '/>'; - } - return tagOpen + '>' + tagContent + '' + this._currentElement.type + '>'; + return mountImage; }, /** @@ -694,6 +705,33 @@ ReactDOMComponent.Mixin = { } }, + _createInitialChildren: function(transaction, props, context, el) { + // Intentional use of != to avoid catching zero/false. + var innerHTML = props.dangerouslySetInnerHTML; + if (innerHTML != null) { + if (innerHTML.__html != null) { + setInnerHTML(el, innerHTML.__html); + } + } else { + var contentToUse = + CONTENT_TYPES[typeof props.children] ? props.children : null; + var childrenToUse = contentToUse != null ? null : props.children; + if (contentToUse != null) { + // TODO: Validate that text is allowed as a child of this node + setTextContent(el, contentToUse); + } else if (childrenToUse != null) { + var mountImages = this.mountChildren( + childrenToUse, + transaction, + processChildContext(context, this) + ); + for (var i = 0; i < mountImages.length; i++) { + el.appendChild(mountImages[i]); + } + } + } + }, + /** * Receives a next element and updates the component. * @@ -747,8 +785,9 @@ ReactDOMComponent.Mixin = { break; } + var node = ReactMount.getNode(this._rootNodeID); assertValidProps(this, nextProps); - this._updateDOMProperties(lastProps, nextProps, transaction); + this._updateDOMProperties(lastProps, nextProps, transaction, node); this._updateDOMChildren( lastProps, nextProps, @@ -783,7 +822,7 @@ ReactDOMComponent.Mixin = { * @param {object} nextProps * @param {ReactReconcileTransaction} transaction */ - _updateDOMProperties: function(lastProps, nextProps, transaction) { + _updateDOMProperties: function(lastProps, nextProps, transaction, node) { var propKey; var styleName; var styleUpdates; @@ -811,10 +850,7 @@ ReactDOMComponent.Mixin = { } else if ( DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) { - BackendIDOperations.deletePropertyByID( - this._rootNodeID, - propKey - ); + DOMPropertyOperations.deleteValueForProperty(node, propKey); } } for (propKey in nextProps) { @@ -867,26 +903,26 @@ ReactDOMComponent.Mixin = { deleteListener(this._rootNodeID, propKey); } } else if (isCustomComponent(this._tag, nextProps)) { - BackendIDOperations.updateAttributeByID( - this._rootNodeID, + DOMPropertyOperations.setValueForAttribute( + node, propKey, nextProp ); } else if ( DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) { - BackendIDOperations.updatePropertyByID( - this._rootNodeID, - propKey, - nextProp - ); + // If we're updating to null or undefined, we should remove the property + // from the DOM node instead of inadvertantly setting to a string. This + // brings us in line with the same behavior we have on initial render. + if (nextProp != null) { + DOMPropertyOperations.setValueForProperty(node, propKey, nextProp); + } else { + DOMPropertyOperations.deleteValueForProperty(node, propKey); + } } } if (styleUpdates) { - BackendIDOperations.updateStylesByID( - this._rootNodeID, - styleUpdates - ); + CSSPropertyOperations.setValueForStyles(node, styleUpdates); } }, @@ -1038,10 +1074,4 @@ assign( ReactMultiChild.Mixin ); -ReactDOMComponent.injection = { - injectIDOperations: function(IDOperations) { - ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations; - }, -}; - module.exports = ReactDOMComponent; diff --git a/src/renderers/dom/shared/ReactDOMFeatureFlags.js b/src/renderers/dom/shared/ReactDOMFeatureFlags.js new file mode 100644 index 0000000000..df1852f9ae --- /dev/null +++ b/src/renderers/dom/shared/ReactDOMFeatureFlags.js @@ -0,0 +1,18 @@ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOMFeatureFlags + */ + +'use strict'; + +var ReactDOMFeatureFlags = { + useCreateElement: false, +}; + +module.exports = ReactDOMFeatureFlags; diff --git a/src/renderers/dom/shared/ReactDOMTextComponent.js b/src/renderers/dom/shared/ReactDOMTextComponent.js index 76e7444a82..7212058905 100644 --- a/src/renderers/dom/shared/ReactDOMTextComponent.js +++ b/src/renderers/dom/shared/ReactDOMTextComponent.js @@ -12,13 +12,15 @@ 'use strict'; +var DOMChildrenOperations = require('DOMChildrenOperations'); var DOMPropertyOperations = require('DOMPropertyOperations'); var ReactComponentBrowserEnvironment = require('ReactComponentBrowserEnvironment'); -var ReactDOMComponent = require('ReactDOMComponent'); +var ReactMount = require('ReactMount'); var assign = require('Object.assign'); var escapeTextContentForBrowser = require('escapeTextContentForBrowser'); +var setTextContent = require('setTextContent'); var validateDOMNesting = require('validateDOMNesting'); /** @@ -77,20 +79,30 @@ assign(ReactDOMTextComponent.prototype, { } this._rootNodeID = rootID; - var escapedText = escapeTextContentForBrowser(this._stringText); + if (transaction.useCreateElement) { + var ownerDocument = context[ReactMount.ownerDocumentContextKey]; + var el = ownerDocument.createElement('span'); + DOMPropertyOperations.setAttributeForID(el, rootID); + // Populate node cache + ReactMount.getID(el); + setTextContent(el, this._stringText); + return el; + } else { + var escapedText = escapeTextContentForBrowser(this._stringText); - if (transaction.renderToStaticMarkup) { - // Normally we'd wrap this in a `span` for the reasons stated above, but - // since this is a situation where React won't take over (static pages), - // we can simply return the text as it is. - return escapedText; + 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 ( + '' + + escapedText + + '' + ); } - - return ( - '' + - escapedText + - '' - ); }, /** @@ -109,10 +121,8 @@ assign(ReactDOMTextComponent.prototype, { // and/or updateComponent to do the actual update for consistency with // other component types? this._stringText = nextStringText; - ReactDOMComponent.BackendIDOperations.updateTextContentByID( - this._rootNodeID, - nextStringText - ); + var node = ReactMount.getNode(this._rootNodeID); + DOMChildrenOperations.updateTextContent(node, nextStringText); } } }, diff --git a/src/renderers/dom/shared/ReactDefaultInjection.js b/src/renderers/dom/shared/ReactDefaultInjection.js index 438a28daa8..bea7540cf1 100644 --- a/src/renderers/dom/shared/ReactDefaultInjection.js +++ b/src/renderers/dom/shared/ReactDefaultInjection.js @@ -23,7 +23,6 @@ var ReactComponentBrowserEnvironment = require('ReactComponentBrowserEnvironment'); var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy'); var ReactDOMComponent = require('ReactDOMComponent'); -var ReactDOMIDOperations = require('ReactDOMIDOperations'); var ReactDOMTextComponent = require('ReactDOMTextComponent'); var ReactEventListener = require('ReactEventListener'); var ReactInjection = require('ReactInjection'); @@ -98,7 +97,6 @@ function inject() { ); ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment); - ReactInjection.DOMComponent.injectIDOperations(ReactDOMIDOperations); if (__DEV__) { var url = (ExecutionEnvironment.canUseDOM && window.location.href) || ''; diff --git a/src/renderers/dom/shared/ReactInjection.js b/src/renderers/dom/shared/ReactInjection.js index 7ad4bcd24d..5508efec56 100644 --- a/src/renderers/dom/shared/ReactInjection.js +++ b/src/renderers/dom/shared/ReactInjection.js @@ -18,7 +18,6 @@ var ReactClass = require('ReactClass'); var ReactEmptyComponent = require('ReactEmptyComponent'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactNativeComponent = require('ReactNativeComponent'); -var ReactDOMComponent = require('ReactDOMComponent'); var ReactPerf = require('ReactPerf'); var ReactRootIndex = require('ReactRootIndex'); var ReactUpdates = require('ReactUpdates'); @@ -26,7 +25,6 @@ var ReactUpdates = require('ReactUpdates'); var ReactInjection = { Component: ReactComponentEnvironment.injection, Class: ReactClass.injection, - DOMComponent: ReactDOMComponent.injection, DOMProperty: DOMProperty.injection, EmptyComponent: ReactEmptyComponent.injection, EventPluginHub: EventPluginHub.injection, diff --git a/src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js b/src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js index 7f28df81dd..fcc67f2c43 100644 --- a/src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js +++ b/src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js @@ -13,6 +13,7 @@ var React = require('React'); var ReactDOM = require('ReactDOM'); +var ReactDOMServer = require('ReactDOMServer'); describe('CSSPropertyOperations', function() { var CSSPropertyOperations; @@ -102,9 +103,8 @@ describe('CSSPropertyOperations', function() { display: null, }; var div =
; - var root = document.createElement('div'); - ReactDOM.render(div, root); - expect(/style=".*"/.test(root.innerHTML)).toBe(false); + var html = ReactDOMServer.renderToString(div); + expect(/style=/.test(html)).toBe(false); }); it('should warn when using hyphenated style names', function() { diff --git a/src/renderers/dom/shared/__tests__/Danger-test.js b/src/renderers/dom/shared/__tests__/Danger-test.js index 811ab51c8e..17dc9d8f6f 100644 --- a/src/renderers/dom/shared/__tests__/Danger-test.js +++ b/src/renderers/dom/shared/__tests__/Danger-test.js @@ -25,7 +25,7 @@ describe('Danger', function() { Danger = require('Danger'); var ReactReconcileTransaction = require('ReactReconcileTransaction'); - transaction = new ReactReconcileTransaction(); + transaction = new ReactReconcileTransaction(/* forceHTML */ true); }); it('should render markup', function() { diff --git a/src/renderers/shared/reconciler/ReactUpdates.js b/src/renderers/shared/reconciler/ReactUpdates.js index aa0f866ade..479488b8ed 100644 --- a/src/renderers/shared/reconciler/ReactUpdates.js +++ b/src/renderers/shared/reconciler/ReactUpdates.js @@ -69,7 +69,7 @@ function ReactUpdatesFlushTransaction() { this.dirtyComponentsLength = null; this.callbackQueue = CallbackQueue.getPooled(); this.reconcileTransaction = - ReactUpdates.ReactReconcileTransaction.getPooled(); + ReactUpdates.ReactReconcileTransaction.getPooled(/* forceHTML */ false); } assign( diff --git a/src/renderers/shared/reconciler/__tests__/ReactMultiChild-test.js b/src/renderers/shared/reconciler/__tests__/ReactMultiChild-test.js index a97dfe9ffb..9358e14513 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactMultiChild-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactMultiChild-test.js @@ -165,6 +165,9 @@ describe('ReactMultiChild', function() { } beforeEach(function() { + var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); + ReactDOMFeatureFlags.useCreateElement = false; + Object.defineProperty(Element.prototype, 'innerHTML', { set: setInnerHTML = jasmine.createSpy().andCallFake( innerHTMLDescriptor.set diff --git a/src/test/ReactDefaultPerfAnalysis.js b/src/test/ReactDefaultPerfAnalysis.js index 3dee0db821..499e3a1f1a 100644 --- a/src/test/ReactDefaultPerfAnalysis.js +++ b/src/test/ReactDefaultPerfAnalysis.js @@ -23,8 +23,6 @@ var DOM_OPERATION_TYPES = { SET_MARKUP: 'set innerHTML', TEXT_CONTENT: 'set textContent', 'updatePropertyByID': 'update attribute', - 'deletePropertyByID': 'delete attribute', - 'updateStylesByID': 'update styles', 'dangerouslyReplaceNodeWithMarkupByID': 'replace', }; diff --git a/src/test/ReactTestUtils.js b/src/test/ReactTestUtils.js index cb64a2954d..1eb2658121 100644 --- a/src/test/ReactTestUtils.js +++ b/src/test/ReactTestUtils.js @@ -399,7 +399,7 @@ ReactShallowRenderer.prototype.render = function(element, context) { if (!context) { context = emptyObject; } - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(false); this._render(element, transaction, context); ReactUpdates.ReactReconcileTransaction.release(transaction); };