@@ -119,8 +119,8 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
119
119
}
120
120
}
121
121
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 ) ) ;
124
124
125
125
if ( t . isStringLiteral ( value ) && ! t . isJSXExpressionContainer ( node . value ) ) {
126
126
value . value = value . value . replace ( / \n \s + / g, ' ' ) ;
@@ -130,6 +130,9 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
130
130
delete value . extra . raw ;
131
131
}
132
132
}
133
+ if ( duplicateChildren && duplicateChildren . length > 0 ) {
134
+ value = t . sequenceExpression ( [ ...duplicateChildren , value ] ) ;
135
+ }
133
136
134
137
if ( t . isJSXNamespacedName ( node . name ) ) {
135
138
node . name = t . stringLiteral (
@@ -281,6 +284,17 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
281
284
function buildJSXOpeningElementAttributes ( attribs , file , children ) {
282
285
let _props = [ ] ;
283
286
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
+
284
298
const hasChildren = children && children . length > 0 ;
285
299
286
300
const useBuiltIns = file . opts . useBuiltIns || false ;
@@ -293,32 +307,48 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
293
307
294
308
while ( attribs . length ) {
295
309
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 ) ) {
297
313
_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
+ }
307
322
} else {
308
- _props . push ( convertAttribute ( prop ) ) ;
323
+ _props . push ( convertAttribute ( prop , duplicateChildren ) ) ;
324
+ if ( duplicateChildren . length > 0 ) {
325
+ duplicateChildren = [ ] ;
326
+ }
309
327
}
310
328
}
311
329
312
330
// In React.JSX, children is no longer a separate argument, but passed in
313
331
// through the argument object
314
332
if ( hasChildren ) {
315
333
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
+ ) ;
317
342
} else {
318
343
_props . push (
319
344
t . objectProperty (
320
345
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 ) ,
322
352
) ,
323
353
) ;
324
354
}
0 commit comments