Skip to content

Commit 4bbd8d2

Browse files
committed
Merge pull request facebook#6164 from gaearon/fix-svg
Don't set children attribute on SVG nodes
2 parents 56c423a + 5eab1bb commit 4bbd8d2

File tree

2 files changed

+111
-20
lines changed

2 files changed

+111
-20
lines changed

‎src/renderers/dom/shared/ReactDOMComponent.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,13 @@ var registrationNameModules = EventPluginRegistry.registrationNameModules;
5353
// For quickly matching children type, to test if can be treated as content.
5454
var CONTENT_TYPES = {'string': true, 'number': true};
5555

56-
var CHILDREN = keyOf({children: null});
5756
var STYLE = keyOf({style: null});
5857
var HTML = keyOf({__html: null});
58+
var RESERVED_PROPS = {
59+
children: null,
60+
dangerouslySetInnerHTML: null,
61+
suppressContentEditableWarning: null,
62+
};
5963

6064
function getDeclarationErrorAddendum(internalInstance) {
6165
if (internalInstance) {
@@ -633,11 +637,13 @@ ReactDOMComponent.Mixin = {
633637
}
634638
var markup = null;
635639
if (this._tag != null && isCustomComponent(this._tag, props)) {
636-
if (propKey !== CHILDREN) {
640+
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
637641
markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
638642
}
639643
} else if (this._namespaceURI === DOMNamespaces.svg) {
640-
markup = DOMPropertyOperations.createMarkupForSVGAttribute(propKey, propValue);
644+
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
645+
markup = DOMPropertyOperations.createMarkupForSVGAttribute(propKey, propValue);
646+
}
641647
} else {
642648
markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
643649
}
@@ -912,20 +918,21 @@ ReactDOMComponent.Mixin = {
912918
deleteListener(this, propKey);
913919
}
914920
} else if (isCustomComponent(this._tag, nextProps)) {
915-
if (propKey === CHILDREN) {
916-
nextProp = null;
921+
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
922+
DOMPropertyOperations.setValueForAttribute(
923+
getNode(this),
924+
propKey,
925+
nextProp
926+
);
917927
}
918-
DOMPropertyOperations.setValueForAttribute(
919-
getNode(this),
920-
propKey,
921-
nextProp
922-
);
923928
} else if (this._namespaceURI === DOMNamespaces.svg) {
924-
DOMPropertyOperations.setValueForSVGAttribute(
925-
getNode(this),
926-
propKey,
927-
nextProp
928-
);
929+
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
930+
DOMPropertyOperations.setValueForSVGAttribute(
931+
getNode(this),
932+
propKey,
933+
nextProp
934+
);
935+
}
929936
} else if (
930937
DOMProperty.properties[propKey] ||
931938
DOMProperty.isCustomAttribute(propKey)) {

‎src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,100 @@ describe('ReactDOMComponent', function() {
244244
expect(stubStyle.display).toEqual('');
245245
});
246246

247-
it('should skip child object attribute on web components', function() {
247+
it('should skip reserved props on web components', function() {
248248
var container = document.createElement('div');
249249

250-
// Test initial render to null
251-
ReactDOM.render(<my-component children={['foo']} />, container);
250+
ReactDOM.render(
251+
<my-component
252+
children={['foo']}
253+
suppressContentEditableWarning={true}
254+
/>,
255+
container
256+
);
252257
expect(container.firstChild.hasAttribute('children')).toBe(false);
258+
expect(
259+
container.firstChild.hasAttribute('suppressContentEditableWarning')
260+
).toBe(false);
253261

254-
// Test updates to null
255-
ReactDOM.render(<my-component children={['foo']} />, container);
262+
ReactDOM.render(
263+
<my-component
264+
children={['bar']}
265+
suppressContentEditableWarning={false}
266+
/>,
267+
container
268+
);
256269
expect(container.firstChild.hasAttribute('children')).toBe(false);
270+
expect(
271+
container.firstChild.hasAttribute('suppressContentEditableWarning')
272+
).toBe(false);
273+
});
274+
275+
it('should skip dangerouslySetInnerHTML on web components', function() {
276+
var container = document.createElement('div');
277+
278+
ReactDOM.render(
279+
<my-component dangerouslySetInnerHTML={{__html: 'hi'}} />,
280+
container
281+
);
282+
expect(
283+
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
284+
).toBe(false);
285+
286+
ReactDOM.render(
287+
<my-component dangerouslySetInnerHTML={{__html: 'bye'}} />,
288+
container
289+
);
290+
expect(
291+
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
292+
).toBe(false);
293+
});
294+
295+
it('should skip reserved props on SVG components', function() {
296+
var container = document.createElement('div');
297+
298+
ReactDOM.render(
299+
<svg
300+
children={['foo']}
301+
suppressContentEditableWarning={true}
302+
/>,
303+
container
304+
);
305+
expect(container.firstChild.hasAttribute('children')).toBe(false);
306+
expect(
307+
container.firstChild.hasAttribute('suppressContentEditableWarning')
308+
).toBe(false);
309+
310+
ReactDOM.render(
311+
<svg
312+
children={['bar']}
313+
suppressContentEditableWarning={false}
314+
/>,
315+
container
316+
);
317+
expect(container.firstChild.hasAttribute('children')).toBe(false);
318+
expect(
319+
container.firstChild.hasAttribute('suppressContentEditableWarning')
320+
).toBe(false);
321+
});
322+
323+
it('should skip dangerouslySetInnerHTML on SVG components', function() {
324+
var container = document.createElement('div');
325+
326+
ReactDOM.render(
327+
<svg dangerouslySetInnerHTML={{__html: 'hi'}} />,
328+
container
329+
);
330+
expect(
331+
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
332+
).toBe(false);
333+
334+
ReactDOM.render(
335+
<svg dangerouslySetInnerHTML={{__html: 'bye'}} />,
336+
container
337+
);
338+
expect(
339+
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
340+
).toBe(false);
257341
});
258342

259343
it('should remove attributes', function() {

0 commit comments

Comments
 (0)