@samitouri / QOS-React-2 / commits / cfd6f7a1b8

Use createElement instead of HTML generation

Behind a feature flag. This is a relatively simple change; adopting this strategy universally would mean that we could clean up a lot of code but this doesn't attempt to restructure more than necessary.

Ben Alpert committed Aug 11, 2015 at 20:52 UTC cfd6f7a1b8bdbe263ec9a8076ee549171fcb9534
19 files changed +183 -140
src/renderers/dom/client/ReactDOMIDOperations.js
+1 -67
@@ -12,7 +12,6 @@
12
13 'use strict';
14
15 -var CSSPropertyOperations = require('CSSPropertyOperations');
15 var DOMChildrenOperations = require('DOMChildrenOperations');
16 var DOMPropertyOperations = require('DOMPropertyOperations');
17 var ReactMount = require('ReactMount');
@@ -33,8 +32,7 @@ var INVALID_PROPERTY_ERRORS = {
32 };
33
34 /**
36 - * Operations used to process updates to DOM nodes. This is made injectable via
37 - * `ReactDOMComponent.BackendIDOperations`.
35 + * Operations used to process updates to DOM nodes.
36 */
37 var ReactDOMIDOperations = {
38
@@ -65,67 +63,6 @@ var ReactDOMIDOperations = {
63 }
64 },
65
68 - /**
69 - * Updates a DOM node with new property values.
70 - *
71 - * @param {string} id ID of the node to update.
72 - * @param {string} name A valid property name.
73 - * @param {*} value New value of the property.
74 - * @internal
75 - */
76 - updateAttributeByID: function(id, name, value) {
77 - var node = ReactMount.getNode(id);
78 - invariant(
79 - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
80 - 'updatePropertyByID(...): %s',
81 - INVALID_PROPERTY_ERRORS[name]
82 - );
83 - DOMPropertyOperations.setValueForAttribute(node, name, value);
84 - },
85 -
86 - /**
87 - * Updates a DOM node to remove a property. This should only be used to remove
88 - * DOM properties in `DOMProperty`.
89 - *
90 - * @param {string} id ID of the node to update.
91 - * @param {string} name A property name to remove, see `DOMProperty`.
92 - * @internal
93 - */
94 - deletePropertyByID: function(id, name, value) {
95 - var node = ReactMount.getNode(id);
96 - invariant(
97 - !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
98 - 'updatePropertyByID(...): %s',
99 - INVALID_PROPERTY_ERRORS[name]
100 - );
101 - DOMPropertyOperations.deleteValueForProperty(node, name, value);
102 - },
103 -
104 - /**
105 - * Updates a DOM node with new style values. If a value is specified as '',
106 - * the corresponding style property will be unset.
107 - *
108 - * @param {string} id ID of the node to update.
109 - * @param {object} styles Mapping from styles to values.
110 - * @internal
111 - */
112 - updateStylesByID: function(id, styles) {
113 - var node = ReactMount.getNode(id);
114 - CSSPropertyOperations.setValueForStyles(node, styles);
115 - },
116 -
117 - /**
118 - * Updates a DOM node's text content set by `props.content`.
119 - *
120 - * @param {string} id ID of the node to update.
121 - * @param {string} content Text content.
122 - * @internal
123 - */
124 - updateTextContentByID: function(id, content) {
125 - var node = ReactMount.getNode(id);
126 - DOMChildrenOperations.updateTextContent(node, content);
127 - },
128 -
66 /**
67 * Replaces a DOM node that exists in the document with markup.
68 *
@@ -156,9 +93,6 @@ var ReactDOMIDOperations = {
93
94 ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
95 updatePropertyByID: 'updatePropertyByID',
159 - deletePropertyByID: 'deletePropertyByID',
160 - updateStylesByID: 'updateStylesByID',
161 - updateTextContentByID: 'updateTextContentByID',
96 dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID',
97 dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates',
98 });
src/renderers/dom/client/ReactMount.js
+39 -4
@@ -14,6 +14,7 @@
14 var DOMProperty = require('DOMProperty');
15 var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
16 var ReactCurrentOwner = require('ReactCurrentOwner');
17 +var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
18 var ReactElement = require('ReactElement');
19 var ReactEmptyComponent = require('ReactEmptyComponent');
20 var ReactInstanceHandles = require('ReactInstanceHandles');
@@ -24,6 +25,7 @@ var ReactReconciler = require('ReactReconciler');
25 var ReactUpdateQueue = require('ReactUpdateQueue');
26 var ReactUpdates = require('ReactUpdates');
27
28 +var assign = require('Object.assign');
29 var emptyObject = require('emptyObject');
30 var containsNode = require('containsNode');
31 var instantiateReactComponent = require('instantiateReactComponent');
@@ -42,6 +44,10 @@ var ELEMENT_NODE_TYPE = 1;
44 var DOC_NODE_TYPE = 9;
45 var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
46
47 +var ownerDocumentContextKey =
48 + '__ReactMount_ownerDocument$' + Math.random().toString(36).slice(2);
49 +
50 +
51 /** Mapping from reactRootID to React component instance. */
52 var instancesByReactRootID = {};
53
@@ -264,6 +270,14 @@ function mountComponentIntoNode(
270 shouldReuseMarkup,
271 context
272 ) {
273 + if (ReactDOMFeatureFlags.useCreateElement) {
274 + context = assign({}, context);
275 + if (container.nodeType === DOC_NODE_TYPE) {
276 + context[ownerDocumentContextKey] = container;
277 + } else {
278 + context[ownerDocumentContextKey] = container.ownerDocument;
279 + }
280 + }
281 if (__DEV__) {
282 if (context === emptyObject) {
283 context = {};
@@ -276,7 +290,12 @@ function mountComponentIntoNode(
290 componentInstance, rootID, transaction, context
291 );
292 componentInstance._renderedComponent._topLevelWrapper = componentInstance;
279 - ReactMount._mountImageIntoNode(markup, container, shouldReuseMarkup);
293 + ReactMount._mountImageIntoNode(
294 + markup,
295 + container,
296 + shouldReuseMarkup,
297 + transaction
298 + );
299 }
300
301 /**
@@ -294,7 +313,9 @@ function batchedMountComponentIntoNode(
313 shouldReuseMarkup,
314 context
315 ) {
297 - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
316 + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
317 + /* forceHTML */ shouldReuseMarkup
318 + );
319 transaction.perform(
320 mountComponentIntoNode,
321 null,
@@ -870,7 +891,12 @@ var ReactMount = {
891 );
892 },
893
873 - _mountImageIntoNode: function(markup, container, shouldReuseMarkup) {
894 + _mountImageIntoNode: function(
895 + markup,
896 + container,
897 + shouldReuseMarkup,
898 + transaction
899 + ) {
900 invariant(
901 container && (
902 container.nodeType === ELEMENT_NODE_TYPE ||
@@ -959,9 +985,18 @@ var ReactMount = {
985 'See React.renderToString() for server rendering.'
986 );
987
962 - setInnerHTML(container, markup);
988 + if (transaction.useCreateElement) {
989 + while (container.lastChild) {
990 + container.removeChild(container.lastChild);
991 + }
992 + container.appendChild(markup);
993 + } else {
994 + setInnerHTML(container, markup);
995 + }
996 },
997
998 + ownerDocumentContextKey: ownerDocumentContextKey,
999 +
1000 /**
1001 * React ID utilities.
1002 */
src/renderers/dom/client/ReactReconcileTransaction.js
+4 -1
@@ -15,6 +15,7 @@
15 var CallbackQueue = require('CallbackQueue');
16 var PooledClass = require('PooledClass');
17 var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
18 +var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
19 var ReactInputSelection = require('ReactInputSelection');
20 var Transaction = require('Transaction');
21
@@ -106,7 +107,7 @@ var TRANSACTION_WRAPPERS = [
107 *
108 * @class ReactReconcileTransaction
109 */
109 -function ReactReconcileTransaction() {
110 +function ReactReconcileTransaction(forceHTML) {
111 this.reinitializeTransaction();
112 // Only server-side rendering really needs this option (see
113 // `ReactServerRendering`), but server-side uses
@@ -115,6 +116,8 @@ function ReactReconcileTransaction() {
116 // `ReactTextComponent` checks it in `mountComponent`.`
117 this.renderToStaticMarkup = false;
118 this.reactMountReady = CallbackQueue.getPooled(null);
119 + this.useCreateElement =
120 + !forceHTML && ReactDOMFeatureFlags.useCreateElement;
121 }
122
123 var Mixin = {
src/renderers/dom/client/utils/DOMChildrenOperations.js
+7 -1
@@ -98,7 +98,13 @@ var DOMChildrenOperations = {
98 }
99 }
100
101 - var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);
101 + var renderedMarkup;
102 + // markupList is either a list of markup or just a list of elements
103 + if (markupList.length && typeof markupList[0] === 'string') {
104 + renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);
105 + } else {
106 + renderedMarkup = markupList;
107 + }
108
109 // Remove updated children first so that `toIndex` is consistent.
110 if (updatedChildren) {
src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js
+2 -2
@@ -62,7 +62,7 @@ describe('ReactDOMTextarea', function() {
62 });
63
64 it('should display "false" for `defaultValue` of `false`', function() {
65 - var stub = <textarea type="text" defaultValue={false} />;
65 + var stub = <textarea defaultValue={false} />;
66 stub = renderTextarea(stub);
67 var node = ReactDOM.findDOMNode(stub);
68
@@ -76,7 +76,7 @@ describe('ReactDOMTextarea', function() {
76 },
77 };
78
79 - var stub = <textarea type="text" defaultValue={objToString} />;
79 + var stub = <textarea defaultValue={objToString} />;
80 stub = renderTextarea(stub);
81 var node = ReactDOM.findDOMNode(stub);
82
src/renderers/dom/server/ReactServerRenderingTransaction.js
+1
@@ -51,6 +51,7 @@ function ReactServerRenderingTransaction(renderToStaticMarkup) {
51 this.reinitializeTransaction();
52 this.renderToStaticMarkup = renderToStaticMarkup;
53 this.reactMountReady = CallbackQueue.getPooled(null);
54 + this.useCreateElement = false;
55 }
56
57 var Mixin = {
src/renderers/dom/shared/DOMPropertyOperations.js
+4
@@ -105,6 +105,10 @@ var DOMPropertyOperations = {
105 quoteAttributeValueForBrowser(id);
106 },
107
108 + setAttributeForID: function(node, id) {
109 + node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
110 + },
111 +
112 /**
113 * Creates markup for a property.
114 *
src/renderers/dom/shared/Danger.js
+6 -1
@@ -172,7 +172,12 @@ var Danger = {
172 'server rendering. See React.renderToString().'
173 );
174
175 - var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
175 + var newChild;
176 + if (typeof markup === 'string') {
177 + newChild = createNodesFromMarkup(markup, emptyFunction)[0];
178 + } else {
179 + newChild = markup;
180 + }
181 oldChild.parentNode.replaceChild(newChild, oldChild);
182 },
183
src/renderers/dom/shared/ReactDOMComponent.js
+65 -35
@@ -37,6 +37,8 @@ var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
37 var invariant = require('invariant');
38 var isEventSupported = require('isEventSupported');
39 var keyOf = require('keyOf');
40 +var setInnerHTML = require('setInnerHTML');
41 +var setTextContent = require('setTextContent');
42 var shallowEqual = require('shallowEqual');
43 var validateDOMNesting = require('validateDOMNesting');
44 var warning = require('warning');
@@ -205,12 +207,6 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
207 );
208 }
209
208 -
209 -/**
210 - * Optionally injectable operations for mutating the DOM
211 - */
212 -var BackendIDOperations = null;
213 -
210 /**
211 * @param {object} component
212 * @param {?object} props
@@ -561,8 +557,26 @@ ReactDOMComponent.Mixin = {
557 }
558 }
559
564 - var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
565 - var tagContent = this._createContentMarkup(transaction, props, context);
560 + var mountImage;
561 + if (transaction.useCreateElement) {
562 + var ownerDocument = context[ReactMount.ownerDocumentContextKey];
563 + var el = ownerDocument.createElement(this._currentElement.type);
564 + DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
565 + // Populate node cache
566 + ReactMount.getID(el);
567 + this._updateDOMProperties({}, props, transaction, el);
568 + this._createInitialChildren(transaction, props, context, el);
569 + mountImage = el;
570 + } else {
571 + var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
572 + var tagContent = this._createContentMarkup(transaction, props, context);
573 + if (!tagContent && omittedCloseTags[this._tag]) {
574 + mountImage = tagOpen + '/>';
575 + } else {
576 + mountImage =
577 + tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
578 + }
579 + }
580
581 switch (this._tag) {
582 case 'button':
@@ -578,10 +592,7 @@ ReactDOMComponent.Mixin = {
592 break;
593 }
594
581 - if (!tagContent && omittedCloseTags[this._tag]) {
582 - return tagOpen + '/>';
583 - }
584 - return tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
595 + return mountImage;
596 },
597
598 /**
@@ -694,6 +705,33 @@ ReactDOMComponent.Mixin = {
705 }
706 },
707
708 + _createInitialChildren: function(transaction, props, context, el) {
709 + // Intentional use of != to avoid catching zero/false.
710 + var innerHTML = props.dangerouslySetInnerHTML;
711 + if (innerHTML != null) {
712 + if (innerHTML.__html != null) {
713 + setInnerHTML(el, innerHTML.__html);
714 + }
715 + } else {
716 + var contentToUse =
717 + CONTENT_TYPES[typeof props.children] ? props.children : null;
718 + var childrenToUse = contentToUse != null ? null : props.children;
719 + if (contentToUse != null) {
720 + // TODO: Validate that text is allowed as a child of this node
721 + setTextContent(el, contentToUse);
722 + } else if (childrenToUse != null) {
723 + var mountImages = this.mountChildren(
724 + childrenToUse,
725 + transaction,
726 + processChildContext(context, this)
727 + );
728 + for (var i = 0; i < mountImages.length; i++) {
729 + el.appendChild(mountImages[i]);
730 + }
731 + }
732 + }
733 + },
734 +
735 /**
736 * Receives a next element and updates the component.
737 *
@@ -747,8 +785,9 @@ ReactDOMComponent.Mixin = {
785 break;
786 }
787
788 + var node = ReactMount.getNode(this._rootNodeID);
789 assertValidProps(this, nextProps);
751 - this._updateDOMProperties(lastProps, nextProps, transaction);
790 + this._updateDOMProperties(lastProps, nextProps, transaction, node);
791 this._updateDOMChildren(
792 lastProps,
793 nextProps,
@@ -783,7 +822,7 @@ ReactDOMComponent.Mixin = {
822 * @param {object} nextProps
823 * @param {ReactReconcileTransaction} transaction
824 */
786 - _updateDOMProperties: function(lastProps, nextProps, transaction) {
825 + _updateDOMProperties: function(lastProps, nextProps, transaction, node) {
826 var propKey;
827 var styleName;
828 var styleUpdates;
@@ -811,10 +850,7 @@ ReactDOMComponent.Mixin = {
850 } else if (
851 DOMProperty.properties[propKey] ||
852 DOMProperty.isCustomAttribute(propKey)) {
814 - BackendIDOperations.deletePropertyByID(
815 - this._rootNodeID,
816 - propKey
817 - );
853 + DOMPropertyOperations.deleteValueForProperty(node, propKey);
854 }
855 }
856 for (propKey in nextProps) {
@@ -867,26 +903,26 @@ ReactDOMComponent.Mixin = {
903 deleteListener(this._rootNodeID, propKey);
904 }
905 } else if (isCustomComponent(this._tag, nextProps)) {
870 - BackendIDOperations.updateAttributeByID(
871 - this._rootNodeID,
906 + DOMPropertyOperations.setValueForAttribute(
907 + node,
908 propKey,
909 nextProp
910 );
911 } else if (
912 DOMProperty.properties[propKey] ||
913 DOMProperty.isCustomAttribute(propKey)) {
878 - BackendIDOperations.updatePropertyByID(
879 - this._rootNodeID,
880 - propKey,
881 - nextProp
882 - );
914 + // If we're updating to null or undefined, we should remove the property
915 + // from the DOM node instead of inadvertantly setting to a string. This
916 + // brings us in line with the same behavior we have on initial render.
917 + if (nextProp != null) {
918 + DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
919 + } else {
920 + DOMPropertyOperations.deleteValueForProperty(node, propKey);
921 + }
922 }
923 }
924 if (styleUpdates) {
886 - BackendIDOperations.updateStylesByID(
887 - this._rootNodeID,
888 - styleUpdates
889 - );
925 + CSSPropertyOperations.setValueForStyles(node, styleUpdates);
926 }
927 },
928
@@ -1038,10 +1074,4 @@ assign(
1074 ReactMultiChild.Mixin
1075 );
1076
1041 -ReactDOMComponent.injection = {
1042 - injectIDOperations: function(IDOperations) {
1043 - ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
1044 - },
1045 -};
1046 -
1077 module.exports = ReactDOMComponent;
src/renderers/dom/shared/ReactDOMFeatureFlags.js new
+18
@@ -0,0 +1,18 @@
1 +/**
2 + * Copyright 2013-2015, 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 + * @providesModule ReactDOMFeatureFlags
10 + */
11 +
12 +'use strict';
13 +
14 +var ReactDOMFeatureFlags = {
15 + useCreateElement: false,
16 +};
17 +
18 +module.exports = ReactDOMFeatureFlags;
src/renderers/dom/shared/ReactDOMTextComponent.js
+27 -17
@@ -12,13 +12,15 @@
12
13 'use strict';
14
15 +var DOMChildrenOperations = require('DOMChildrenOperations');
16 var DOMPropertyOperations = require('DOMPropertyOperations');
17 var ReactComponentBrowserEnvironment =
18 require('ReactComponentBrowserEnvironment');
18 -var ReactDOMComponent = require('ReactDOMComponent');
19 +var ReactMount = require('ReactMount');
20
21 var assign = require('Object.assign');
22 var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
23 +var setTextContent = require('setTextContent');
24 var validateDOMNesting = require('validateDOMNesting');
25
26 /**
@@ -77,20 +79,30 @@ assign(ReactDOMTextComponent.prototype, {
79 }
80
81 this._rootNodeID = rootID;
80 - var escapedText = escapeTextContentForBrowser(this._stringText);
82 + if (transaction.useCreateElement) {
83 + var ownerDocument = context[ReactMount.ownerDocumentContextKey];
84 + var el = ownerDocument.createElement('span');
85 + DOMPropertyOperations.setAttributeForID(el, rootID);
86 + // Populate node cache
87 + ReactMount.getID(el);
88 + setTextContent(el, this._stringText);
89 + return el;
90 + } else {
91 + var escapedText = escapeTextContentForBrowser(this._stringText);
92
82 - if (transaction.renderToStaticMarkup) {
83 - // Normally we'd wrap this in a `span` for the reasons stated above, but
84 - // since this is a situation where React won't take over (static pages),
85 - // we can simply return the text as it is.
86 - return escapedText;
87 - }
93 + if (transaction.renderToStaticMarkup) {
94 + // Normally we'd wrap this in a `span` for the reasons stated above, but
95 + // since this is a situation where React won't take over (static pages),
96 + // we can simply return the text as it is.
97 + return escapedText;
98 + }
99
89 - return (
90 - '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
91 - escapedText +
92 - '</span>'
93 - );
100 + return (
101 + '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
102 + escapedText +
103 + '</span>'
104 + );
105 + }
106 },
107
108 /**
@@ -109,10 +121,8 @@ assign(ReactDOMTextComponent.prototype, {
121 // and/or updateComponent to do the actual update for consistency with
122 // other component types?
123 this._stringText = nextStringText;
112 - ReactDOMComponent.BackendIDOperations.updateTextContentByID(
113 - this._rootNodeID,
114 - nextStringText
115 - );
124 + var node = ReactMount.getNode(this._rootNodeID);
125 + DOMChildrenOperations.updateTextContent(node, nextStringText);
126 }
127 }
128 },
src/renderers/dom/shared/ReactDefaultInjection.js
-2
@@ -23,7 +23,6 @@ var ReactComponentBrowserEnvironment =
23 require('ReactComponentBrowserEnvironment');
24 var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
25 var ReactDOMComponent = require('ReactDOMComponent');
26 -var ReactDOMIDOperations = require('ReactDOMIDOperations');
26 var ReactDOMTextComponent = require('ReactDOMTextComponent');
27 var ReactEventListener = require('ReactEventListener');
28 var ReactInjection = require('ReactInjection');
@@ -98,7 +97,6 @@ function inject() {
97 );
98
99 ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
101 - ReactInjection.DOMComponent.injectIDOperations(ReactDOMIDOperations);
100
101 if (__DEV__) {
102 var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
src/renderers/dom/shared/ReactInjection.js
-2
@@ -18,7 +18,6 @@ var ReactClass = require('ReactClass');
18 var ReactEmptyComponent = require('ReactEmptyComponent');
19 var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
20 var ReactNativeComponent = require('ReactNativeComponent');
21 -var ReactDOMComponent = require('ReactDOMComponent');
21 var ReactPerf = require('ReactPerf');
22 var ReactRootIndex = require('ReactRootIndex');
23 var ReactUpdates = require('ReactUpdates');
@@ -26,7 +25,6 @@ var ReactUpdates = require('ReactUpdates');
25 var ReactInjection = {
26 Component: ReactComponentEnvironment.injection,
27 Class: ReactClass.injection,
29 - DOMComponent: ReactDOMComponent.injection,
28 DOMProperty: DOMProperty.injection,
29 EmptyComponent: ReactEmptyComponent.injection,
30 EventPluginHub: EventPluginHub.injection,
src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js
+3 -3
@@ -13,6 +13,7 @@
13
14 var React = require('React');
15 var ReactDOM = require('ReactDOM');
16 +var ReactDOMServer = require('ReactDOMServer');
17
18 describe('CSSPropertyOperations', function() {
19 var CSSPropertyOperations;
@@ -102,9 +103,8 @@ describe('CSSPropertyOperations', function() {
103 display: null,
104 };
105 var div = <div style={styles} />;
105 - var root = document.createElement('div');
106 - ReactDOM.render(div, root);
107 - expect(/style=".*"/.test(root.innerHTML)).toBe(false);
106 + var html = ReactDOMServer.renderToString(div);
107 + expect(/style=/.test(html)).toBe(false);
108 });
109
110 it('should warn when using hyphenated style names', function() {
src/renderers/dom/shared/__tests__/Danger-test.js
+1 -1
@@ -25,7 +25,7 @@ describe('Danger', function() {
25 Danger = require('Danger');
26
27 var ReactReconcileTransaction = require('ReactReconcileTransaction');
28 - transaction = new ReactReconcileTransaction();
28 + transaction = new ReactReconcileTransaction(/* forceHTML */ true);
29 });
30
31 it('should render markup', function() {
src/renderers/shared/reconciler/ReactUpdates.js
+1 -1
@@ -69,7 +69,7 @@ function ReactUpdatesFlushTransaction() {
69 this.dirtyComponentsLength = null;
70 this.callbackQueue = CallbackQueue.getPooled();
71 this.reconcileTransaction =
72 - ReactUpdates.ReactReconcileTransaction.getPooled();
72 + ReactUpdates.ReactReconcileTransaction.getPooled(/* forceHTML */ false);
73 }
74
75 assign(
src/renderers/shared/reconciler/__tests__/ReactMultiChild-test.js
+3
@@ -165,6 +165,9 @@ describe('ReactMultiChild', function() {
165 }
166
167 beforeEach(function() {
168 + var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
169 + ReactDOMFeatureFlags.useCreateElement = false;
170 +
171 Object.defineProperty(Element.prototype, 'innerHTML', {
172 set: setInnerHTML = jasmine.createSpy().andCallFake(
173 innerHTMLDescriptor.set
src/test/ReactDefaultPerfAnalysis.js
-2
@@ -23,8 +23,6 @@ var DOM_OPERATION_TYPES = {
23 SET_MARKUP: 'set innerHTML',
24 TEXT_CONTENT: 'set textContent',
25 'updatePropertyByID': 'update attribute',
26 - 'deletePropertyByID': 'delete attribute',
27 - 'updateStylesByID': 'update styles',
26 'dangerouslyReplaceNodeWithMarkupByID': 'replace',
27 };
28
src/test/ReactTestUtils.js
+1 -1
@@ -399,7 +399,7 @@ ReactShallowRenderer.prototype.render = function(element, context) {
399 if (!context) {
400 context = emptyObject;
401 }
402 - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
402 + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(false);
403 this._render(element, transaction, context);
404 ReactUpdates.ReactReconcileTransaction.release(transaction);
405 };