Skip to content

Commit

Permalink
Handle nested levels of spread properties (Fixes jsx-eslint#771)
Browse files Browse the repository at this point in the history
  • Loading branch information
petersendidit committed Aug 16, 2016
1 parent 976b9d2 commit b9a8aff
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
22 changes: 18 additions & 4 deletions lib/rules/no-danger-with-children.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,30 @@ module.exports = {
schema: [] // no options
},
create: function(context) {
function findSpreadVariable(name) {
return variableUtil.variablesInScope(context).find(function (item) {
return item.name === name;
});
}
/**
* Takes a ObjectExpression and returns the value of the prop if it has it
* @param {object} node - ObjectExpression node
* @param {string} propName - name of the prop to look for
*/
function findObjectProp(node, propName) {
if (!node.properties) {
return false;
}
return node.properties.find(function(prop) {
return prop.key.name === propName;
if (prop.type === 'Property') {
return prop.key.name === propName;
} else if (prop.type === 'ExperimentalSpreadProperty') {
var variable = findSpreadVariable(prop.argument.name);
if (variable && variable.defs[0].node.init) {
return findObjectProp(variable.defs[0].node.init, propName);
}
}
return false;
});
}

Expand All @@ -39,9 +55,7 @@ module.exports = {
var attributes = node.openingElement.attributes;
return attributes.find(function (attribute) {
if (attribute.type === 'JSXSpreadAttribute') {
var variable = variableUtil.variablesInScope(context).find(function (item) {
return item.name === attribute.argument.name;
});
var variable = findSpreadVariable(attribute.argument.name);
if (variable && variable.defs[0].node.init) {
return findObjectProp(variable.defs[0].node.init, propName);
}
Expand Down
23 changes: 21 additions & 2 deletions tests/lib/rules/no-danger-with-children.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var RuleTester = require('eslint').RuleTester;
var parserOptions = {
ecmaVersion: 6,
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true
}
};
Expand Down Expand Up @@ -46,11 +47,20 @@ ruleTester.run('no-danger-with-children', rule, {
},
{
code: [
'const props = { children: "Children" };',
'const moreProps = { className: "eslint" };',
'const props = { children: "Children", ...moreProps };',
'<div {...props} />'
].join('\n'),
parserOptions: parserOptions
},
{
code: [
'const otherProps = { children: "Children" };',
'const { a, b, ...props } = otherProps;',
'<div {...props} />',
].join('\n'),
parserOptions: parserOptions
},
{
code: '<Hello>Children</Hello>',
parserOptions: parserOptions
Expand Down Expand Up @@ -103,7 +113,6 @@ ruleTester.run('no-danger-with-children', rule, {
code: [
'const props = { children: "Children", dangerouslySetInnerHTML: { __html: "HTML" } };',
'<div {...props} />',
'//foobar'
].join('\n'),
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
parserOptions: parserOptions
Expand Down Expand Up @@ -185,6 +194,16 @@ ruleTester.run('no-danger-with-children', rule, {
].join('\n'),
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
parserOptions: parserOptions
},
{
code: [
'const moreProps = { children: "Children" };',
'const otherProps = { ...moreProps };',
'const props = { ...otherProps, dangerouslySetInnerHTML: { __html: "HTML" } };',
'React.createElement("div", props);'
].join('\n'),
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
parserOptions: parserOptions
}
]
});

0 comments on commit b9a8aff

Please sign in to comment.