Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't set children attribute on SVG nodes #6164

Merged
merged 1 commit into from
Mar 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions src/renderers/dom/shared/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ var registrationNameModules = EventPluginRegistry.registrationNameModules;
// For quickly matching children type, to test if can be treated as content.
var CONTENT_TYPES = {'string': true, 'number': true};

var CHILDREN = keyOf({children: null});
var STYLE = keyOf({style: null});
var HTML = keyOf({__html: null});
var RESERVED_PROPS = {
children: null,
dangerouslySetInnerHTML: null,
suppressContentEditableWarning: null,
};

function getDeclarationErrorAddendum(internalInstance) {
if (internalInstance) {
Expand Down Expand Up @@ -633,11 +637,13 @@ ReactDOMComponent.Mixin = {
}
var markup = null;
if (this._tag != null && isCustomComponent(this._tag, props)) {
if (propKey !== CHILDREN) {
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
}
} else if (this._namespaceURI === DOMNamespaces.svg) {
markup = DOMPropertyOperations.createMarkupForSVGAttribute(propKey, propValue);
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
markup = DOMPropertyOperations.createMarkupForSVGAttribute(propKey, propValue);
}
} else {
markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
}
Expand Down Expand Up @@ -912,20 +918,21 @@ ReactDOMComponent.Mixin = {
deleteListener(this, propKey);
}
} else if (isCustomComponent(this._tag, nextProps)) {
if (propKey === CHILDREN) {
nextProp = null;
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
DOMPropertyOperations.setValueForAttribute(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gaearon this implementation doesn't allow to pass values other than strings to a custom element. How do I pass an array, object or function?

getNode(this),
propKey,
nextProp
);
}
DOMPropertyOperations.setValueForAttribute(
getNode(this),
propKey,
nextProp
);
} else if (this._namespaceURI === DOMNamespaces.svg) {
DOMPropertyOperations.setValueForSVGAttribute(
getNode(this),
propKey,
nextProp
);
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
DOMPropertyOperations.setValueForSVGAttribute(
getNode(this),
propKey,
nextProp
);
}
} else if (
DOMProperty.properties[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
Expand Down
94 changes: 89 additions & 5 deletions src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,100 @@ describe('ReactDOMComponent', function() {
expect(stubStyle.display).toEqual('');
});

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

// Test initial render to null
ReactDOM.render(<my-component children={['foo']} />, container);
ReactDOM.render(
<my-component
children={['foo']}
suppressContentEditableWarning={true}
/>,
container
);
expect(container.firstChild.hasAttribute('children')).toBe(false);
expect(
container.firstChild.hasAttribute('suppressContentEditableWarning')
).toBe(false);

// Test updates to null
ReactDOM.render(<my-component children={['foo']} />, container);
ReactDOM.render(
<my-component
children={['bar']}
suppressContentEditableWarning={false}
/>,
container
);
expect(container.firstChild.hasAttribute('children')).toBe(false);
expect(
container.firstChild.hasAttribute('suppressContentEditableWarning')
).toBe(false);
});

it('should skip dangerouslySetInnerHTML on web components', function() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made this a separate test because can’t check children and dangerouslySetInnerHTML at the same time.

var container = document.createElement('div');

ReactDOM.render(
<my-component dangerouslySetInnerHTML={{__html: 'hi'}} />,
container
);
expect(
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
).toBe(false);

ReactDOM.render(
<my-component dangerouslySetInnerHTML={{__html: 'bye'}} />,
container
);
expect(
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
).toBe(false);
});

it('should skip reserved props on SVG components', function() {
var container = document.createElement('div');

ReactDOM.render(
<svg
children={['foo']}
suppressContentEditableWarning={true}
/>,
container
);
expect(container.firstChild.hasAttribute('children')).toBe(false);
expect(
container.firstChild.hasAttribute('suppressContentEditableWarning')
).toBe(false);

ReactDOM.render(
<svg
children={['bar']}
suppressContentEditableWarning={false}
/>,
container
);
expect(container.firstChild.hasAttribute('children')).toBe(false);
expect(
container.firstChild.hasAttribute('suppressContentEditableWarning')
).toBe(false);
});

it('should skip dangerouslySetInnerHTML on SVG components', function() {
var container = document.createElement('div');

ReactDOM.render(
<svg dangerouslySetInnerHTML={{__html: 'hi'}} />,
container
);
expect(
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
).toBe(false);

ReactDOM.render(
<svg dangerouslySetInnerHTML={{__html: 'bye'}} />,
container
);
expect(
container.firstChild.hasAttribute('dangerouslySetInnerHTML')
).toBe(false);
});

it('should remove attributes', function() {
Expand Down