Skip to content

Commit

Permalink
feat(restructure): support RestElement
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiyuanzmj committed Sep 10, 2024
1 parent 9f1a148 commit 87ac6b6
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 13 deletions.
57 changes: 44 additions & 13 deletions src/core/transformRestructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
babelParse,
generateTransform,
getLang,
importHelperFn,
walkAST,
} from '@vue-macros/common'
import { walkIdentifiers } from '@vue-vapor/compiler-core'
Expand All @@ -18,12 +19,25 @@ export function transformRestructure(code: string, id: string) {
enter(node) {
if (isFunctionExpression(node)) {
const result = new Map()
const restResult = new Map()
for (const param of node.params) {
const paths = `_ctx${index++}`
if (resolveParams(param, paths, result)) {
if (resolveParam(param, paths, result, restResult)) {
s.overwrite(param.start!, param.end!, paths)
}
}

if (restResult.size) {
for (const [key, value] of restResult) {
const result = `${key} = ${importHelperFn(s, 0, 'createPropsRestProxy', 'vue')}(${value})`
if (node.body.type === 'BlockStatement') {
s.appendRight(node.body.start! + 1, `const ${result};`)
} else {
s.appendRight(node.body.start!, `(${result},`)
s.appendRight(node.body.end!, ')')
}
}
}
if (!result.size) return

walkIdentifiers(
Expand All @@ -48,30 +62,47 @@ export function transformRestructure(code: string, id: string) {
return generateTransform(s, id)
}

function resolveParams(
function resolveParam(
param: Node,
paths: string = '',
result: Map<string, string>,
restResult: Map<string, string>,
) {
const elements =
const properties =
param.type === 'ObjectPattern'
? param.properties
: param.type === 'ArrayPattern'
? param.elements
: []
if (!elements.length) return
if (!properties.length) return

elements.forEach((element, index) => {
if (element?.type === 'Identifier') {
result.set(element.name, `${paths}[${index}]`)
const propNames: string[] = []
properties.forEach((prop, index) => {
if (prop?.type === 'Identifier') {
result.set(prop.name, `${paths}[${index}]`)
propNames.push(`'${prop.name}'`)
} else if (
prop?.type === 'ObjectProperty' &&
prop.key.type === 'Identifier'
) {
if (
!resolveParam(
prop.value,
`${paths}.${prop.key.name}`,
result,
restResult,
)
) {
result.set(prop.key.name, `${paths}.${prop.key.name}`)
propNames.push(`'${prop.key.name}'`)
}
} else if (
element?.type === 'ObjectProperty' &&
element.key.type === 'Identifier'
prop?.type === 'RestElement' &&
prop?.argument.type === 'Identifier'
) {
if (!resolveParams(element.value, `${paths}.${element.key.name}`, result))
result.set(element.key.name, `${paths}.${element.key.name}`)
} else if (element) {
resolveParams(element, `${paths}[${index}]`, result)
restResult.set(prop.argument.name, `${paths}, [${propNames.join(', ')}]`)
} else if (prop) {
resolveParam(prop, `${paths}[${index}]`, result, restResult)
}
})
return true
Expand Down
34 changes: 34 additions & 0 deletions test/transformReconstruct.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,38 @@ describe('transform', () => {
`,
)
})

test('reconstruct arrowFunctionExpression', () => {
const { code } = transformRestructure(
`const App = ([{root: {foo, ...rest}}]) => (
<>{[foo, rest]}</>
)`,
'tsx',
)!
expect(code).toMatchInlineSnapshot(
`
"
import { createPropsRestProxy as __MACROS_createPropsRestProxy } from "vue";const App = (_ctx0) => (
(rest = __MACROS_createPropsRestProxy(_ctx0[0].root, ['foo']),<>{[_ctx0[0].root.foo, rest]}</>)
)"
`,
)
})

test('reconstruct functionDeclaration', () => {
const { code } = transformRestructure(
`function App({foo, ...rest}){
return <>{[foo, rest]}</>
}`,
'tsx',
)!
expect(code).toMatchInlineSnapshot(
`
"
import { createPropsRestProxy as __MACROS_createPropsRestProxy } from "vue";function App(_ctx0){const rest = __MACROS_createPropsRestProxy(_ctx0, ['foo']);
return <>{[_ctx0.foo, rest]}</>
}"
`,
)
})
})

0 comments on commit 87ac6b6

Please sign in to comment.