Skip to content

Commit 324ebf1

Browse files
committed
Handle nested levels of spread properties (Fixes jsx-eslint#771)
1 parent 976b9d2 commit 324ebf1

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

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

+15-4
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,27 @@ 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) {
2833
return node.properties.find(function(prop) {
29-
return prop.key.name === propName;
34+
if (prop.type === 'Property') {
35+
return prop.key.name === propName;
36+
} else if (prop.type === 'ExperimentalSpreadProperty') {
37+
var variable = findSpreadVariable(prop.argument.name);
38+
if (variable && variable.defs[0].node.init) {
39+
return findObjectProp(variable.defs[0].node.init, propName);
40+
}
41+
}
42+
return false;
3043
});
3144
}
3245

@@ -39,9 +52,7 @@ module.exports = {
3952
var attributes = node.openingElement.attributes;
4053
return attributes.find(function (attribute) {
4154
if (attribute.type === 'JSXSpreadAttribute') {
42-
var variable = variableUtil.variablesInScope(context).find(function (item) {
43-
return item.name === attribute.argument.name;
44-
});
55+
var variable = findSpreadVariable(attribute.argument.name);
4556
if (variable && variable.defs[0].node.init) {
4657
return findObjectProp(variable.defs[0].node.init, propName);
4758
}

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

+13-1
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,7 +47,8 @@ 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
@@ -185,6 +187,16 @@ ruleTester.run('no-danger-with-children', rule, {
185187
].join('\n'),
186188
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
187189
parserOptions: parserOptions
190+
},
191+
{
192+
code: [
193+
'const moreProps = { children: "Children" };',
194+
'const otherProps = { ...moreProps };',
195+
'const props = { ...otherProps, dangerouslySetInnerHTML: { __html: "HTML" } };',
196+
'React.createElement("div", props);'
197+
].join('\n'),
198+
errors: [{message: 'Only set one of `children` or `props.dangerouslySetInnerHTML`'}],
199+
parserOptions: parserOptions
188200
}
189201
]
190202
});

0 commit comments

Comments
 (0)