Skip to content

Commit eec22a3

Browse files
committed
refactor(compiler): prevent covert ObjectExpression to ObjectPattern for v-for and v-slot
1 parent 2570920 commit eec22a3

File tree

11 files changed

+27
-89
lines changed

11 files changed

+27
-89
lines changed

docs/features/directives.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export default () => (
6060

6161
## `v-slot`, `v-slots`
6262

63+
> [!WARNING]
64+
> Due to the inability to generate a correct AST for directive expressions with default values (e.g., `v-slot={({ foo = '' })}`), so default values are not supported.
65+
6366
::: code-group
6467

6568
```tsx [v-slot] twoslash

docs/zh/features/directives.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export default () => (
6060

6161
## `v-slot`, `v-slots`
6262

63+
> [!WARNING]
64+
> 由于无法为带有默认值的指令表达式(例如 `v-slot={({ foo = '' })}`)生成正确的 AST,因此不支持默认值。
65+
6366
::: code-group
6467

6568
```tsx [v-slot] twoslash

packages/compiler/src/generators/component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ function genSlotBlockWithProps(oper: SlotBlockIRNode, context: CodegenContext) {
346346
propsName = `_slotProps${depth}`
347347
walkIdentifiers(
348348
props.ast,
349-
(id, _, __, ___, isLocal) => {
350-
if (isLocal) idsOfProps.add(id.name)
349+
(id, _, __, isReference, isLocal) => {
350+
if (isReference && !isLocal) idsOfProps.add(id.name)
351351
},
352352
true,
353353
)

packages/compiler/src/generators/for.ts

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ export function genFor(
213213
if (value.ast && value.ast.type !== 'Identifier') {
214214
walkIdentifiers(
215215
value.ast,
216-
(id, _, parentStack, ___, isLocal) => {
217-
if (isLocal) {
216+
(id, _, parentStack, isReference, isLocal) => {
217+
if (isReference && !isLocal) {
218218
let path = ''
219219
let isDynamic = false
220220
let helper
@@ -239,16 +239,16 @@ export function genFor(
239239
// non-computed, can only be identifier
240240
path += `.${(parent.key as Identifier).name}`
241241
}
242-
} else if (parent.type === 'ArrayPattern') {
242+
} else if (parent.type === 'ArrayExpression') {
243243
const index = parent.elements.indexOf(child as any)
244-
if (child.type === 'RestElement') {
244+
if (child.type === 'SpreadElement') {
245245
path += `.slice(${index})`
246246
} else {
247247
path += `[${index}]`
248248
}
249249
} else if (
250-
parent.type === 'ObjectPattern' &&
251-
child.type === 'RestElement'
250+
parent.type === 'ObjectExpression' &&
251+
child.type === 'SpreadElement'
252252
) {
253253
helper = context.helper('getRestElement')
254254
helperArgs = `[${parent.properties
@@ -268,20 +268,6 @@ export function genFor(
268268
})
269269
.join(', ')}]`
270270
}
271-
272-
// default value
273-
if (
274-
child.type === 'AssignmentPattern' &&
275-
(parent.type === 'ObjectProperty' ||
276-
parent.type === 'ArrayPattern')
277-
) {
278-
isDynamic = true
279-
helper = context.helper('getDefaultValue')
280-
helperArgs = value.content.slice(
281-
child.right.start! - 1,
282-
child.right.end! - 1,
283-
)
284-
}
285271
}
286272
map.set(id.name, { path, dynamic: isDynamic, helper, helperArgs })
287273
}

packages/compiler/src/transforms/vFor.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
import {
88
createBranch,
99
createCompilerError,
10-
createExpressionWithFn,
1110
ErrorCodes,
1211
findProp,
1312
isConstantNode,
@@ -92,12 +91,11 @@ export function getForParseResult(
9291
) {
9392
if (dir.value.expression.left.type === 'SequenceExpression') {
9493
const expressions = dir.value.expression.left.expressions
95-
value =
96-
expressions[0] && createExpressionWithFn(expressions[0], context)
94+
value = expressions[0] && resolveExpression(expressions[0], context)
9795
key = expressions[1] && resolveExpression(expressions[1], context)
9896
index = expressions[2] && resolveExpression(expressions[2], context)
9997
} else {
100-
value = createExpressionWithFn(dir.value.expression.left, context)
98+
value = resolveExpression(dir.value.expression.left, context)
10199
}
102100
source = resolveExpression(dir.value.expression.right, context)
103101
}

packages/compiler/src/transforms/vSlot.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ export const transformVSlot: NodeTransform = (node, context) => {
3131
const { children } = node
3232

3333
const dir = findProp(node, 'v-slot')
34-
const resolvedDirective = dir
35-
? resolveDirective(dir, context, true)
36-
: undefined
34+
const resolvedDirective = dir ? resolveDirective(dir, context) : undefined
3735
const { parent } = context
3836

3937
const isComponent = isJSXComponent(node)

packages/compiler/src/utils/directive.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import type { DirectiveNode } from '../ir'
22
import type { TransformContext } from '../transform'
3-
import {
4-
createExpressionWithFn,
5-
createSimpleExpression,
6-
resolveExpression,
7-
} from './expression'
3+
import { createSimpleExpression, resolveExpression } from './expression'
84
import { getText } from './text'
95
import type { JSXAttribute } from '@babel/types'
106

117
const namespaceRE = /^(?:\$([\w-]+)\$)?([\w-]+)?/
128
export function resolveDirective(
139
node: JSXAttribute,
1410
context: TransformContext,
15-
withFn = false,
1611
): DirectiveNode {
1712
const { value, name } = node
1813
let nameString =
@@ -49,11 +44,7 @@ export function resolveDirective(
4944
: undefined
5045
: createSimpleExpression(nameString, true, name)
5146

52-
const exp = value
53-
? withFn && value.type === 'JSXExpressionContainer'
54-
? createExpressionWithFn(value.expression, context)
55-
: resolveExpression(value, context)
56-
: undefined
47+
const exp = value ? resolveExpression(value, context) : undefined
5748

5849
return {
5950
name: isDirective ? nameString.slice(2) : 'bind',

packages/compiler/src/utils/expression.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,6 @@ export function resolveExpression(
8282
return createSimpleExpression(source, isStatic, node)
8383
}
8484

85-
export function createExpressionWithFn(node: Node, context: TransformContext) {
86-
const text = getText(node, context)
87-
return node.type === 'Identifier'
88-
? createSimpleExpression(text, false, node)
89-
: createSimpleExpression(
90-
text,
91-
false,
92-
parseExpression(`(${text})=>{}`, {
93-
plugins: context.options.expressionPlugins,
94-
}),
95-
)
96-
}
97-
9885
export function propToExpression(
9986
prop: JSXAttribute,
10087
context: TransformContext,

packages/compiler/test/transforms/__snapshots__/vFor.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ exports[`compiler: v-for > v-for aliases w/ complex expressions 1`] = `
195195
const n0 = _createFor(() => (list), (_for_item0) => {
196196
const n2 = t0()
197197
const x2 = _child(n2)
198-
_setNodes(x2, () => (_for_item0.value.foo + bar + baz + _for_item0.value.baz[0] + quux))
198+
_setNodes(x2, () => (_for_item0.value.foo + baz + _for_item0.value.baz[0]))
199199
return n2
200200
})
201201
return n0

packages/compiler/test/transforms/vFor.spec.ts

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,7 @@ describe('compiler: v-for', () => {
215215
value: {
216216
content: '{ id, value }',
217217
ast: {
218-
type: 'ArrowFunctionExpression',
219-
params: [
220-
{
221-
type: 'ObjectPattern',
222-
},
223-
],
218+
type: 'ObjectExpression',
224219
},
225220
},
226221
key: undefined,
@@ -243,12 +238,7 @@ describe('compiler: v-for', () => {
243238
value: {
244239
content: '{ id, ...other }',
245240
ast: {
246-
type: 'ArrowFunctionExpression',
247-
params: [
248-
{
249-
type: 'ObjectPattern',
250-
},
251-
],
241+
type: 'ObjectExpression',
252242
},
253243
},
254244
key: {
@@ -272,12 +262,7 @@ describe('compiler: v-for', () => {
272262
value: {
273263
content: '[id, other]',
274264
ast: {
275-
type: 'ArrowFunctionExpression',
276-
params: [
277-
{
278-
type: 'ArrayPattern',
279-
},
280-
],
265+
type: 'ArrayExpression',
281266
},
282267
},
283268
key: {
@@ -302,12 +287,7 @@ describe('compiler: v-for', () => {
302287
value: {
303288
content: '[id, ...other]',
304289
ast: {
305-
type: 'ArrowFunctionExpression',
306-
params: [
307-
{
308-
type: 'ArrayPattern',
309-
},
310-
],
290+
type: 'ArrayExpression',
311291
},
312292
},
313293
key: {
@@ -320,7 +300,7 @@ describe('compiler: v-for', () => {
320300
test('v-for aliases w/ complex expressions', () => {
321301
const { code, ir } = compileWithVFor(
322302
`<div v-for={({ foo, baz: [qux] }) in list}>
323-
{ foo + bar + baz + qux + quux }
303+
{ foo + baz + qux }
324304
</div>`,
325305
)
326306
expect(code).matchSnapshot()
@@ -333,12 +313,7 @@ describe('compiler: v-for', () => {
333313
value: {
334314
content: '{ foo, baz: [qux] }',
335315
ast: {
336-
type: 'ArrowFunctionExpression',
337-
params: [
338-
{
339-
type: 'ObjectPattern',
340-
},
341-
],
316+
type: 'ObjectExpression',
342317
},
343318
},
344319
key: undefined,

0 commit comments

Comments
 (0)