Skip to content

Commit 65beba9

Browse files
committed
fix(slots): differentiate dynamic/static compiled slots
fix #1557
1 parent ba3b3cd commit 65beba9

File tree

7 files changed

+141
-118
lines changed

7 files changed

+141
-118
lines changed

packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const _withId = /*#__PURE__*/_withScopeId(\\"test\\")
4141
export const render = /*#__PURE__*/_withId(function render(_ctx, _cache) {
4242
const _component_Child = _resolveComponent(\\"Child\\")
4343
44-
return (_openBlock(), _createBlock(_component_Child, null, _createSlots({ _: 1 }, [
44+
return (_openBlock(), _createBlock(_component_Child, null, _createSlots({ _: 2 }, [
4545
(_ctx.ok)
4646
? {
4747
name: \\"foo\\",

packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ return function render(_ctx, _cache) {
99
return (_openBlock(), _createBlock(_component_Comp, null, {
1010
[_ctx.one]: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),
1111
[_ctx.two]: _withCtx(({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)]),
12-
_: 1
12+
_: 2
1313
}, 1024 /* DYNAMIC_SLOTS */))
1414
}"
1515
`;
@@ -35,7 +35,7 @@ exports[`compiler: transform component slots named slot with v-for w/ prefixIden
3535
return function render(_ctx, _cache) {
3636
const _component_Comp = _resolveComponent(\\"Comp\\")
3737
38-
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 1 }, [
38+
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 }, [
3939
_renderList(_ctx.list, (name) => {
4040
return {
4141
name: name,
@@ -52,7 +52,7 @@ exports[`compiler: transform component slots named slot with v-if + prefixIdenti
5252
return function render(_ctx, _cache) {
5353
const _component_Comp = _resolveComponent(\\"Comp\\")
5454
55-
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 1 }, [
55+
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 }, [
5656
(_ctx.ok)
5757
? {
5858
name: \\"one\\",
@@ -72,7 +72,7 @@ return function render(_ctx, _cache) {
7272
7373
const _component_Comp = _resolveComponent(\\"Comp\\")
7474
75-
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 1 }, [
75+
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 }, [
7676
ok
7777
? {
7878
name: \\"one\\",
@@ -101,7 +101,7 @@ return function render(_ctx, _cache) {
101101
102102
const _component_Comp = _resolveComponent(\\"Comp\\")
103103
104-
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 1 }, [
104+
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 }, [
105105
ok
106106
? {
107107
name: \\"one\\",
@@ -145,7 +145,7 @@ return function render(_ctx, _cache) {
145145
default: _withCtx(({ foo }) => [
146146
_createVNode(_component_Inner, null, {
147147
default: _withCtx(({ bar }) => [_toDisplayString(foo), _toDisplayString(bar), _toDisplayString(_ctx.baz)]),
148-
_: 1
148+
_: 2
149149
}, 1024 /* DYNAMIC_SLOTS */),
150150
\\" \\",
151151
_toDisplayString(foo),
@@ -165,8 +165,8 @@ return function render(_ctx, _cache) {
165165
166166
return (_openBlock(), _createBlock(_component_Comp, null, {
167167
[_ctx.named]: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),
168-
_: 1
169-
}))
168+
_: 2
169+
}, 1024 /* DYNAMIC_SLOTS */))
170170
}"
171171
`;
172172

packages/compiler-core/__tests__/transforms/vSlot.spec.ts

+102-93
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
5353
}
5454
}
5555

56-
function createSlotMatcher(obj: Record<string, any>) {
56+
function createSlotMatcher(obj: Record<string, any>, isDynamic = false) {
5757
return {
5858
type: NodeTypes.JS_OBJECT_EXPRESSION,
5959
properties: Object.keys(obj)
@@ -70,7 +70,7 @@ function createSlotMatcher(obj: Record<string, any>) {
7070
})
7171
.concat({
7272
key: { content: `_` },
73-
value: { content: `1`, isStatic: false }
73+
value: { content: isDynamic ? `2` : `1`, isStatic: false }
7474
})
7575
}
7676
}
@@ -230,29 +230,32 @@ describe('compiler: transform component slots', () => {
230230
{ prefixIdentifiers: true }
231231
)
232232
expect(slots).toMatchObject(
233-
createSlotMatcher({
234-
'[_ctx.named]': {
235-
type: NodeTypes.JS_FUNCTION_EXPRESSION,
236-
params: {
237-
type: NodeTypes.COMPOUND_EXPRESSION,
238-
children: [`{ `, { content: `foo` }, ` }`]
239-
},
240-
returns: [
241-
{
242-
type: NodeTypes.INTERPOLATION,
243-
content: {
244-
content: `foo`
245-
}
233+
createSlotMatcher(
234+
{
235+
'[_ctx.named]': {
236+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
237+
params: {
238+
type: NodeTypes.COMPOUND_EXPRESSION,
239+
children: [`{ `, { content: `foo` }, ` }`]
246240
},
247-
{
248-
type: NodeTypes.INTERPOLATION,
249-
content: {
250-
content: `_ctx.bar`
241+
returns: [
242+
{
243+
type: NodeTypes.INTERPOLATION,
244+
content: {
245+
content: `foo`
246+
}
247+
},
248+
{
249+
type: NodeTypes.INTERPOLATION,
250+
content: {
251+
content: `_ctx.bar`
252+
}
251253
}
252-
}
253-
]
254-
}
255-
})
254+
]
255+
}
256+
},
257+
true
258+
)
256259
)
257260
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
258261
})
@@ -307,50 +310,53 @@ describe('compiler: transform component slots', () => {
307310
{ prefixIdentifiers: true }
308311
)
309312
expect(slots).toMatchObject(
310-
createSlotMatcher({
311-
'[_ctx.one]': {
312-
type: NodeTypes.JS_FUNCTION_EXPRESSION,
313-
params: {
314-
type: NodeTypes.COMPOUND_EXPRESSION,
315-
children: [`{ `, { content: `foo` }, ` }`]
316-
},
317-
returns: [
318-
{
319-
type: NodeTypes.INTERPOLATION,
320-
content: {
321-
content: `foo`
322-
}
313+
createSlotMatcher(
314+
{
315+
'[_ctx.one]': {
316+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
317+
params: {
318+
type: NodeTypes.COMPOUND_EXPRESSION,
319+
children: [`{ `, { content: `foo` }, ` }`]
323320
},
324-
{
325-
type: NodeTypes.INTERPOLATION,
326-
content: {
327-
content: `_ctx.bar`
321+
returns: [
322+
{
323+
type: NodeTypes.INTERPOLATION,
324+
content: {
325+
content: `foo`
326+
}
327+
},
328+
{
329+
type: NodeTypes.INTERPOLATION,
330+
content: {
331+
content: `_ctx.bar`
332+
}
328333
}
329-
}
330-
]
331-
},
332-
'[_ctx.two]': {
333-
type: NodeTypes.JS_FUNCTION_EXPRESSION,
334-
params: {
335-
type: NodeTypes.COMPOUND_EXPRESSION,
336-
children: [`{ `, { content: `bar` }, ` }`]
334+
]
337335
},
338-
returns: [
339-
{
340-
type: NodeTypes.INTERPOLATION,
341-
content: {
342-
content: `_ctx.foo`
343-
}
336+
'[_ctx.two]': {
337+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
338+
params: {
339+
type: NodeTypes.COMPOUND_EXPRESSION,
340+
children: [`{ `, { content: `bar` }, ` }`]
344341
},
345-
{
346-
type: NodeTypes.INTERPOLATION,
347-
content: {
348-
content: `bar`
342+
returns: [
343+
{
344+
type: NodeTypes.INTERPOLATION,
345+
content: {
346+
content: `_ctx.foo`
347+
}
348+
},
349+
{
350+
type: NodeTypes.INTERPOLATION,
351+
content: {
352+
content: `bar`
353+
}
349354
}
350-
}
351-
]
352-
}
353-
})
355+
]
356+
}
357+
},
358+
true
359+
)
354360
)
355361
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
356362
})
@@ -382,35 +388,38 @@ describe('compiler: transform component slots', () => {
382388
type: NodeTypes.VNODE_CALL,
383389
tag: `_component_Inner`,
384390
props: undefined,
385-
children: createSlotMatcher({
386-
default: {
387-
type: NodeTypes.JS_FUNCTION_EXPRESSION,
388-
params: {
389-
type: NodeTypes.COMPOUND_EXPRESSION,
390-
children: [`{ `, { content: `bar` }, ` }`]
391-
},
392-
returns: [
393-
{
394-
type: NodeTypes.INTERPOLATION,
395-
content: {
396-
content: `foo`
397-
}
398-
},
399-
{
400-
type: NodeTypes.INTERPOLATION,
401-
content: {
402-
content: `bar`
403-
}
391+
children: createSlotMatcher(
392+
{
393+
default: {
394+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
395+
params: {
396+
type: NodeTypes.COMPOUND_EXPRESSION,
397+
children: [`{ `, { content: `bar` }, ` }`]
404398
},
405-
{
406-
type: NodeTypes.INTERPOLATION,
407-
content: {
408-
content: `_ctx.baz`
399+
returns: [
400+
{
401+
type: NodeTypes.INTERPOLATION,
402+
content: {
403+
content: `foo`
404+
}
405+
},
406+
{
407+
type: NodeTypes.INTERPOLATION,
408+
content: {
409+
content: `bar`
410+
}
411+
},
412+
{
413+
type: NodeTypes.INTERPOLATION,
414+
content: {
415+
content: `_ctx.baz`
416+
}
409417
}
410-
}
411-
]
412-
}
413-
}),
418+
]
419+
}
420+
},
421+
true
422+
),
414423
// nested slot should be forced dynamic, since scope variables
415424
// are not tracked as dependencies of the slot.
416425
patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS)
@@ -522,7 +531,7 @@ describe('compiler: transform component slots', () => {
522531
callee: CREATE_SLOTS,
523532
arguments: [
524533
createObjectMatcher({
525-
_: `[1]`
534+
_: `[2]`
526535
}),
527536
{
528537
type: NodeTypes.JS_ARRAY_EXPRESSION,
@@ -564,7 +573,7 @@ describe('compiler: transform component slots', () => {
564573
callee: CREATE_SLOTS,
565574
arguments: [
566575
createObjectMatcher({
567-
_: `[1]`
576+
_: `[2]`
568577
}),
569578
{
570579
type: NodeTypes.JS_ARRAY_EXPRESSION,
@@ -613,7 +622,7 @@ describe('compiler: transform component slots', () => {
613622
callee: CREATE_SLOTS,
614623
arguments: [
615624
createObjectMatcher({
616-
_: `[1]`
625+
_: `[2]`
617626
}),
618627
{
619628
type: NodeTypes.JS_ARRAY_EXPRESSION,
@@ -672,7 +681,7 @@ describe('compiler: transform component slots', () => {
672681
callee: CREATE_SLOTS,
673682
arguments: [
674683
createObjectMatcher({
675-
_: `[1]`
684+
_: `[2]`
676685
}),
677686
{
678687
type: NodeTypes.JS_ARRAY_EXPRESSION,

packages/compiler-core/src/transforms/vSlot.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export function buildSlots(
135135
let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0
136136
// with `prefixIdentifiers: true`, this can be further optimized to make
137137
// it dynamic only when the slot actually uses the scope variables.
138-
if (!__BROWSER__ && context.prefixIdentifiers) {
138+
if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) {
139139
hasDynamicSlots = hasScopeRef(node, context.identifiers)
140140
}
141141

@@ -144,6 +144,9 @@ export function buildSlots(
144144
const onComponentSlot = findDir(node, 'slot', true)
145145
if (onComponentSlot) {
146146
const { arg, exp } = onComponentSlot
147+
if (arg && !isStaticExp(arg)) {
148+
hasDynamicSlots = true
149+
}
147150
slotsProperties.push(
148151
createObjectProperty(
149152
arg || createSimpleExpression('default', true),
@@ -317,7 +320,12 @@ export function buildSlots(
317320

318321
let slots = createObjectExpression(
319322
slotsProperties.concat(
320-
createObjectProperty(`_`, createSimpleExpression(`1`, false))
323+
createObjectProperty(
324+
`_`,
325+
// 2 = compiled but dynamic = can skip normalization, but must run diff
326+
// 1 = compiled and static = can skip normalization AND diff as optimized
327+
createSimpleExpression(hasDynamicSlots ? `2` : `1`, false)
328+
)
321329
),
322330
loc
323331
) as SlotsExpression

packages/compiler-ssr/__tests__/ssrComponent.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ describe('ssr: components', () => {
140140
return function ssrRender(_ctx, _push, _parent, _attrs) {
141141
const _component_foo = _resolveComponent(\\"foo\\")
142142
143-
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 1 }, [
143+
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 2 }, [
144144
(_ctx.ok)
145145
? {
146146
name: \\"named\\",
@@ -172,7 +172,7 @@ describe('ssr: components', () => {
172172
return function ssrRender(_ctx, _push, _parent, _attrs) {
173173
const _component_foo = _resolveComponent(\\"foo\\")
174174
175-
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 1 }, [
175+
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 2 }, [
176176
_renderList(_ctx.names, (key) => {
177177
return {
178178
name: key,

0 commit comments

Comments
 (0)