Skip to content

Commit b1002a6

Browse files
committed
single function as children should keep it
1 parent 6f847c4 commit b1002a6

File tree

4 files changed

+91
-15
lines changed

4 files changed

+91
-15
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,7 @@ dist
103103
# TernJS port file
104104
.tern-port
105105

106+
# vscode config
107+
.vscode
108+
106109
dist

packages/babel-plugin-jsx/src/transform-vue-jsx.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
parseDirectives,
1414
isFragment,
1515
walksScope,
16+
isSingleFunctionChild
1617
} from './utils';
1718
import { PatchFlags, PatchFlagNames } from './patchFlags';
1819
import { State, ExcludesBoolean } from './';
@@ -405,26 +406,32 @@ const transformJSXElement = (
405406
));
406407
}
407408

409+
const isSingleFunctionChildren: Boolean = isSingleFunctionChild(path.get('children'))
410+
408411
// @ts-ignore
409412
const createVNode = t.callExpression(createIdentifier(state, usePatchFlag ? 'createVNode' : 'h'), [
410413
tag,
411414
// @ts-ignore
412415
compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props,
413-
(children.length || slots) ? (
414-
isComponent
415-
? t.objectExpression([
416-
!!children.length && t.objectProperty(
417-
t.identifier('default'),
418-
t.arrowFunctionExpression([], t.arrayExpression(children))
419-
),
420-
...(slots ? (
421-
t.isObjectExpression(slots)
422-
? (slots as any as t.ObjectExpression).properties
423-
: [t.spreadElement(slots as any)]
424-
) : [])
425-
].filter(Boolean as any as ExcludesBoolean))
426-
: t.arrayExpression(children)
427-
) : t.nullLiteral(),
416+
isSingleFunctionChildren
417+
?
418+
children[0]
419+
:
420+
(children.length || slots) ? (
421+
isComponent
422+
? t.objectExpression([
423+
!!children.length && t.objectProperty(
424+
t.identifier('default'),
425+
t.arrowFunctionExpression([], t.arrayExpression(children))
426+
),
427+
...(slots ? (
428+
t.isObjectExpression(slots)
429+
? (slots as any as t.ObjectExpression).properties
430+
: [t.spreadElement(slots as any)]
431+
) : [])
432+
].filter(Boolean as any as ExcludesBoolean))
433+
: t.arrayExpression(children)
434+
) : t.nullLiteral(),
428435
!!patchFlag && usePatchFlag && (
429436
useOptimate
430437
? t.addComment(t.numericLiteral(patchFlag), 'trailing', ` ${flagNames} `, false)

packages/babel-plugin-jsx/src/utils.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,37 @@ const walksScope = (path: NodePath, name: string) => {
281281
}
282282
}
283283

284+
const isSingleFunctionChild = (paths: NodePath<
285+
t.JSXText
286+
| t.JSXExpressionContainer
287+
| t.JSXSpreadChild
288+
| t.JSXElement
289+
| t.JSXFragment
290+
>[],) => {
291+
if (paths.length !== 1) return false
292+
if (t.isJSXExpressionContainer(paths[0])) {
293+
let p = paths[0].get('expression')
294+
if (t.isArrowFunctionExpression(p) || t.isFunctionExpression(p)) return true
295+
if (t.isIdentifier(p)) {
296+
const ip = p as NodePath<t.Identifier>
297+
const node = ip.node
298+
if (ip.scope.hasBinding(node.name)) {
299+
const binding = ip.scope.getBinding(node.name)
300+
if (binding) {
301+
// TODO: if binding still a variableDeclarator
302+
const bp = binding.path
303+
const dt = bp.get('declarations').find((xp) => t.isVariableDeclarator(xp) && ((xp.node as t.VariableDeclarator).id as t.Identifier).name === node.name)
304+
const init = dt && dt.get('init')
305+
console.log(t.isFunctionExpression(init), t.isArrowFunctionExpression(init))
306+
return t.isFunctionExpression(init) || t.isArrowFunctionExpression(init)
307+
}
308+
}
309+
return ip.scope.hasBinding(node.name) && (t.isFunctionExpression(ip.scope.bindings[0]) || t.isArrowFunctionExpression(ip.scope.bindings[0]))
310+
}
311+
}
312+
return false
313+
}
314+
284315
export {
285316
createIdentifier,
286317
isDirective,
@@ -294,4 +325,5 @@ export {
294325
parseDirectives,
295326
isFragment,
296327
walksScope,
328+
isSingleFunctionChild
297329
};

packages/babel-plugin-jsx/test/index.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,40 @@ describe('slots', () => {
306306

307307
expect(wrapper.html()).toBe('<div>foo</div>');
308308
});
309+
310+
test('pass only single function as children should keep it', () => {
311+
const A = (_, { slots }) => (
312+
<div>
313+
{slots.default()}
314+
</div>
315+
);
316+
317+
const wrapper = mount({
318+
setup() {
319+
return () => <A>{() => 'foo'}</A>;
320+
},
321+
});
322+
323+
expect(wrapper.html()).toBe('<div>foo</div>');
324+
});
325+
326+
test('pass only single variable of function should keep it', () => {
327+
const A = (_, { slots }) => (
328+
<div>
329+
{slots.default()}
330+
</div>
331+
);
332+
333+
const renderA = () => 'foo';
334+
335+
const wrapper = mount({
336+
setup() {
337+
return () => <A>{renderA}</A>;
338+
},
339+
});
340+
341+
expect(wrapper.html()).toBe('<div>foo</div>');
342+
});
309343
});
310344

311345
describe('PatchFlags', () => {

0 commit comments

Comments
 (0)