@@ -119,8 +119,8 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
119119 }
120120 }
121121
122- function convertAttribute ( node ) {
123- const value = convertAttributeValue ( node . value || t . booleanLiteral ( true ) ) ;
122+ function convertAttribute ( node , duplicateChildren ) {
123+ let value = convertAttributeValue ( node . value || t . booleanLiteral ( true ) ) ;
124124
125125 if ( t . isStringLiteral ( value ) && ! t . isJSXExpressionContainer ( node . value ) ) {
126126 value . value = value . value . replace ( / \n \s + / g, ' ' ) ;
@@ -130,6 +130,9 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
130130 delete value . extra . raw ;
131131 }
132132 }
133+ if ( duplicateChildren && duplicateChildren . length > 0 ) {
134+ value = t . sequenceExpression ( [ ...duplicateChildren , value ] ) ;
135+ }
133136
134137 if ( t . isJSXNamespacedName ( node . name ) ) {
135138 node . name = t . stringLiteral (
@@ -281,6 +284,17 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
281284 function buildJSXOpeningElementAttributes ( attribs , file , children ) {
282285 let _props = [ ] ;
283286 const objs = [ ] ;
287+
288+ // In order to avoid having duplicate "children" keys, we avoid
289+ // pushing the "children" prop if we have actual children. However,
290+ // the children prop may have side effects, so to be certain
291+ // these side effects are evaluated, we add them to the following prop
292+ // as a sequence expression to preserve order. So:
293+ // <div children={x++} foo={y}>{child}</div> becomes
294+ // React.jsx('div', {foo: (x++, y), children: child});
295+ // duplicateChildren contains the extra children prop values
296+ let duplicateChildren = [ ] ;
297+
284298 const hasChildren = children && children . length > 0 ;
285299
286300 const useBuiltIns = file . opts . useBuiltIns || false ;
@@ -293,32 +307,48 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
293307
294308 while ( attribs . length ) {
295309 const prop = attribs . shift ( ) ;
296- if ( t . isJSXSpreadAttribute ( prop ) ) {
310+ if ( hasChildren && isChildrenProp ( prop ) ) {
311+ duplicateChildren . push ( convertAttributeValue ( prop . value ) ) ;
312+ } else if ( t . isJSXSpreadAttribute ( prop ) ) {
297313 _props = pushProps ( _props , objs ) ;
298- objs . push ( prop . argument ) ;
299- } else if ( hasChildren && isChildrenProp ( prop ) ) {
300- // In order to avoid having duplicate "children" keys, we avoid
301- // pushing the "children" prop if we have actual children. Instead
302- // we put the children into a separate object and then rely on
303- // the Object.assign logic below to ensure the correct object is
304- // formed.
305- _props = pushProps ( _props , objs ) ;
306- objs . push ( t . objectExpression ( [ convertAttribute ( prop ) ] ) ) ;
314+ if ( duplicateChildren . length > 0 ) {
315+ objs . push (
316+ t . sequenceExpression ( [ ...duplicateChildren , prop . argument ] ) ,
317+ ) ;
318+ duplicateChildren = [ ] ;
319+ } else {
320+ objs . push ( prop . argument ) ;
321+ }
307322 } else {
308- _props . push ( convertAttribute ( prop ) ) ;
323+ _props . push ( convertAttribute ( prop , duplicateChildren ) ) ;
324+ if ( duplicateChildren . length > 0 ) {
325+ duplicateChildren = [ ] ;
326+ }
309327 }
310328 }
311329
312330 // In React.JSX, children is no longer a separate argument, but passed in
313331 // through the argument object
314332 if ( hasChildren ) {
315333 if ( children . length === 1 ) {
316- _props . push ( t . objectProperty ( t . identifier ( 'children' ) , children [ 0 ] ) ) ;
334+ _props . push (
335+ t . objectProperty (
336+ t . identifier ( 'children' ) ,
337+ duplicateChildren . length > 0
338+ ? t . sequenceExpression ( [ ...duplicateChildren , children [ 0 ] ] )
339+ : children [ 0 ] ,
340+ ) ,
341+ ) ;
317342 } else {
318343 _props . push (
319344 t . objectProperty (
320345 t . identifier ( 'children' ) ,
321- t . arrayExpression ( children ) ,
346+ duplicateChildren . length > 0
347+ ? t . sequenceExpression ( [
348+ ...duplicateChildren ,
349+ t . arrayExpression ( children ) ,
350+ ] )
351+ : t . arrayExpression ( children ) ,
322352 ) ,
323353 ) ;
324354 }
0 commit comments