Skip to content

Commit 973fede

Browse files
committed
feat(compiler): support spread attribute
1 parent eb5ee01 commit 973fede

File tree

7 files changed

+432
-98
lines changed

7 files changed

+432
-98
lines changed

playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"dev": "nodemon -w '../../src/**/*.ts' -e .ts -x vite --port 5174"
77
},
88
"dependencies": {
9-
"@vue-macros/define-render": "^1.5.5",
9+
"unplugin-vue-macros": "^2.9.5",
1010
"vite-plugin-vue-devtools": "^7.3.4",
1111
"vue": "npm:@vue-vapor/[email protected]"
1212
},

playground/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"module": "esnext",
99
"moduleResolution": "node",
1010
"resolveJsonModule": true,
11-
"types": ["vite/client"],
11+
"types": ["vite/client", "unplugin-vue-macros/macros-global"],
1212
"strict": true,
1313
"strictNullChecks": true,
1414
"esModuleInterop": true

playground/vite.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { defineConfig } from 'vite'
22
import Inspect from 'vite-plugin-inspect'
33
import Vue from '@vitejs/plugin-vue'
4-
import defineRender from '@vue-macros/define-render/vite'
4+
import VueMacros from 'unplugin-vue-macros/vite'
55
import Devtools from 'vite-plugin-vue-devtools'
66
import VueJsxVapor from '../src/vite'
77

88
export default defineConfig({
9-
plugins: [Vue(), VueJsxVapor(), defineRender(), Inspect(), Devtools()],
9+
plugins: [Vue(), VueJsxVapor(), VueMacros(), Inspect(), Devtools()],
1010
})

pnpm-lock.yaml

Lines changed: 366 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/compiler/transforms/transformElement.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ import {
1616
type IRPropsDynamicAttribute,
1717
type IRPropsStatic,
1818
} from '../ir'
19-
import { isComponentNode, resolveSimpleExpression } from '../utils'
19+
import {
20+
isComponentNode,
21+
resolveExpression,
22+
resolveSimpleExpression,
23+
} from '../utils'
2024
import { EMPTY_EXPRESSION } from './utils'
2125
import type { SimpleExpressionNode } from '@vue-vapor/compiler-dom'
2226
import type { JSXAttribute, JSXElement, JSXSpreadAttribute } from '@babel/types'
@@ -205,6 +209,17 @@ export function buildProps(
205209
}
206210

207211
for (const prop of props) {
212+
if (prop.type === 'JSXSpreadAttribute' && prop.argument) {
213+
const value = resolveExpression(prop.argument, context)
214+
dynamicExpr.push(value)
215+
pushMergeArg()
216+
dynamicArgs.push({
217+
kind: IRDynamicPropsKind.EXPRESSION,
218+
value,
219+
})
220+
continue
221+
}
222+
208223
const result = transformProp(prop, node, context)
209224
if (result) {
210225
dynamicExpr.push(result.key, result.value)

test/transforms/transformChildren.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { describe, expect, test } from 'vitest'
22

3+
import { NodeTypes } from '@vue-vapor/compiler-core'
4+
import { IRDynamicPropsKind, IRNodeTypes } from '@vue-vapor/compiler-vapor'
35
import {
46
transformChildren,
57
transformElement,
68
transformText,
9+
transformVBind,
710
// transformVIf,
811
} from '../../src/core/compiler'
912
import { makeCompile } from './_utils'
@@ -15,6 +18,7 @@ const compileWithElementTransform = makeCompile({
1518
transformElement,
1619
transformChildren,
1720
],
21+
directiveTransforms: { bind: transformVBind },
1822
})
1923

2024
describe('compiler: children transform', () => {
@@ -52,4 +56,46 @@ describe('compiler: children transform', () => {
5256
'template',
5357
])
5458
})
59+
60+
test.only('v-bind="obj"', () => {
61+
const { code, ir } = compileWithElementTransform(`<div {...obj} />`)
62+
expect(code).toMatchInlineSnapshot(`
63+
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
64+
const t0 = _template("<div></div>")
65+
66+
export function render(_ctx) {
67+
const n0 = t0()
68+
_renderEffect(() => _setDynamicProps(n0, _ctx.obj))
69+
return n0
70+
}"
71+
`)
72+
expect(ir.block.effect).toMatchObject([
73+
{
74+
expressions: [
75+
{
76+
type: NodeTypes.SIMPLE_EXPRESSION,
77+
content: 'obj',
78+
isStatic: false,
79+
},
80+
],
81+
operations: [
82+
{
83+
type: IRNodeTypes.SET_DYNAMIC_PROPS,
84+
element: 0,
85+
props: [
86+
{
87+
kind: IRDynamicPropsKind.EXPRESSION,
88+
value: {
89+
type: NodeTypes.SIMPLE_EXPRESSION,
90+
content: 'obj',
91+
isStatic: false,
92+
},
93+
},
94+
],
95+
},
96+
],
97+
},
98+
])
99+
expect(code).contains('_setDynamicProps(n0, _ctx.obj)')
100+
})
55101
})

test/transforms/vBind.spec.ts

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -38,96 +38,6 @@ describe('compiler v-bind', () => {
3838
expect(ir.block.effect).lengthOf(1)
3939
expect(ir.block.effect[0].expressions).lengthOf(1)
4040
expect(ir.block.effect[0].operations).lengthOf(1)
41-
expect(ir.block.effect[0].operations).toMatchInlineSnapshot(`
42-
[
43-
{
44-
"element": 0,
45-
"prop": {
46-
"key": {
47-
"ast": null,
48-
"constType": 3,
49-
"content": "id",
50-
"isStatic": true,
51-
"loc": {
52-
"end": {
53-
"column": 8,
54-
"line": 1,
55-
"offset": 7,
56-
},
57-
"source": "id",
58-
"start": {
59-
"column": 6,
60-
"line": 1,
61-
"offset": 5,
62-
},
63-
},
64-
"type": 4,
65-
},
66-
"loc": SourceLocation {
67-
"end": Position {
68-
"column": 12,
69-
"index": 12,
70-
"line": 1,
71-
},
72-
"filename": undefined,
73-
"identifierName": undefined,
74-
"start": Position {
75-
"column": 5,
76-
"index": 5,
77-
"line": 1,
78-
},
79-
},
80-
"modifier": undefined,
81-
"runtimeCamelize": false,
82-
"value": undefined,
83-
"values": [
84-
{
85-
"ast": Node {
86-
"comments": [],
87-
"end": 3,
88-
"errors": [],
89-
"loc": SourceLocation {
90-
"end": Position {
91-
"column": 3,
92-
"index": 3,
93-
"line": 1,
94-
},
95-
"filename": undefined,
96-
"identifierName": "id",
97-
"start": Position {
98-
"column": 1,
99-
"index": 1,
100-
"line": 1,
101-
},
102-
},
103-
"name": "id",
104-
"start": 1,
105-
"type": "Identifier",
106-
},
107-
"constType": 0,
108-
"content": "id",
109-
"isStatic": false,
110-
"loc": {
111-
"end": {
112-
"column": 13,
113-
"line": 1,
114-
"offset": 12,
115-
},
116-
"source": "id",
117-
"start": {
118-
"column": 9,
119-
"line": 1,
120-
"offset": 8,
121-
},
122-
},
123-
"type": 4,
124-
},
125-
],
126-
},
127-
"type": 2,
128-
},
129-
]
130-
`)
13141
expect(ir.block.effect[0]).toMatchObject({
13242
expressions: [
13343
{

0 commit comments

Comments
 (0)