Skip to content

Commit 4c0706b

Browse files
petersendidityannickcr
authored andcommitted
Fix nested spread handling in no-danger-with-children (fixes jsx-eslint#771)
1 parent 976b9d2 commit 4c0706b

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

lib/rules/no-danger-with-children.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,30 @@ module.exports = {
1919
schema: [] // no options
2020
},
2121
create: function(context) {
22+
function findSpreadVariable(name) {
23+
return variableUtil.variablesInScope(context).find(function (item) {
24+
return item.name === name;
25+
});
26+
}
2227
/**
2328
* Takes a ObjectExpression and returns the value of the prop if it has it
2429
* @param {object} node - ObjectExpression node
2530
* @param {string} propName - name of the prop to look for
2631
*/
2732
function findObjectProp(node, propName) {
33+
if (!node.properties) {
34+
return false;
35+
}
2836
return node.properties.find(function(prop) {
29-
return prop.key.name === propName;
37+
if (prop.type === 'Property') {
38+
return prop.key.name === propName;
39+
} else if (prop.type === 'ExperimentalSpreadProperty') {
40+
var variable = findSpreadVariable(prop.argument.name);
41+
if (variable && variable.defs[0].node.init) {
42+
return findObjectProp(variable.defs[0].node.init, propName);
43+
}
44+
}
45+
return false;
3046
});
3147
}
3248

@@ -39,9 +55,7 @@ module.exports = {
3955
var attributes = node.openingElement.attributes;
4056
return attributes.find(function (attribute) {
4157
if (attribute.type === 'JSXSpreadAttribute') {
42-
var variable = variableUtil.variablesInScope(context).find(function (item) {
43-
return item.name === attribute.argument.name;
44-
});
58+
var variable = findSpreadVariable(attribute.argument.name);
4559
if (variable && variable.defs[0].node.init) {
4660
return findObjectProp(variable.defs[0].node.init, propName);
4761
}

tests/lib/rules/no-danger-with-children.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var RuleTester = require('eslint').RuleTester;
1414
var parserOptions = {
1515
ecmaVersion: 6,
1616
ecmaFeatures: {
17+
experimentalObjectRestSpread: true,
1718
jsx: true
1819
}
1920
};
@@ -46,11 +47,20 @@ ruleTester.run('no-danger-with-children', rule, {
4647
},
4748
{
4849
code: [
49-
'const props = { children: "Children" };',
50+
'const moreProps = { className: "eslint" };',
51+
'const props = { children: "Children", ...moreProps };',
5052
'<div {...props} />'
5153
].join('\n'),
5254
parserOptions: parserOptions
5355
},
56+
{
57+
code: [
58+
'const otherProps = { children: "Children" };',
59+
'const { a, b, ...props } = otherProps;',
60+
'<div {...props} />',
61+
].join('\n'),
62+
parserOptions: parserOptions
63+
},
5464
{
5565
code: '<Hello>Children</Hello>',
5666
parserOptions: parserOptions
@@ -103,7 +113,6 @@ ruleTester.run('no-danger-with-children', rule, {
103113
code: [
104114
'const props = { children: "Children", dangerouslySetInnerHTML: { __html: "HTML" } };',
105115
'<div {...props} />',
106-
'//foobar'
107116
].join('\n'),
108117
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
109118
parserOptions: parserOptions
@@ -185,6 +194,16 @@ ruleTester.run('no-danger-with-children', rule, {
185194
].join('\n'),
186195
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
187196
parserOptions: parserOptions
197+
},
198+
{
199+
code: [
200+
'const moreProps = { children: "Children" };',
201+
'const otherProps = { ...moreProps };',
202+
'const props = { ...otherProps, dangerouslySetInnerHTML: { __html: "HTML" } };',
203+
'React.createElement("div", props);'
204+
].join('\n'),
205+
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
206+
parserOptions: parserOptions
188207
}
189208
]
190209
});

0 commit comments

Comments
 (0)