Skip to content

Commit

Permalink
fix(reactivity-transform): unwrap wrapper node
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Dec 13, 2022
1 parent 3f703db commit d8f131a
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 32 deletions.
14 changes: 14 additions & 0 deletions packages/compiler-core/src/babelUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,17 @@ function isReferenced(node: Node, parent: Node, grandparent?: Node): boolean {

return true
}

export const TS_NODE_TYPES = [
'TSNonNullExpression', // foo!
'TSAsExpression', // foo as number
'TSTypeAssertion', // (<number>foo)
'TSInstantiationExpression' // foo<string>
]
export function unwrapTSNode(node: Node): Node {
if (TS_NODE_TYPES.includes(node.type)) {
return unwrapTSNode((node as any).expression)
} else {
return node
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,23 @@ return () => {}
}"
`;

exports[`sfc props transform unwrap TS node 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { toDisplayString as _toDisplayString } from "vue"
export default /*#__PURE__*/_defineComponent({
props: ['foo'],
setup(__props) {
console.log(__props.foo)
return (_ctx: any,_cache: any) => {
return _toDisplayString(__props.foo)
}
}
})"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,23 @@ describe('sfc props transform', () => {
})
})

test('unwrap TS node', () => {
const { content, bindings } = compile(`
<script setup lang="ts">
const { foo } = defineProps(['foo'])! as any
console.log(foo)
</script>
<template>{{ foo }}</template>
`)
expect(content).not.toMatch(`const { foo } =`)
expect(content).toMatch(`console.log(__props.foo)`)
expect(content).toMatch(`_toDisplayString(__props.foo)`)
assertCode(content)
expect(bindings).toStrictEqual({
foo: BindingTypes.PROPS
})
})

describe('errors', () => {
test('should error on deep destructure', () => {
expect(() =>
Expand Down
26 changes: 15 additions & 11 deletions packages/compiler-sfc/src/compileScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
UNREF,
SimpleExpressionNode,
isFunctionType,
walkIdentifiers
walkIdentifiers,
unwrapTSNode
} from '@vue/compiler-dom'
import { DEFAULT_FILENAME, SFCDescriptor, SFCScriptBlock } from './parse'
import {
Expand Down Expand Up @@ -1184,16 +1185,17 @@ export function compileScript(
}

if (node.type === 'ExpressionStatement') {
const expr = unwrapTSNode(node.expression)
// process `defineProps` and `defineEmit(s)` calls
if (
processDefineProps(node.expression) ||
processDefineEmits(node.expression) ||
processWithDefaults(node.expression)
processDefineProps(expr) ||
processDefineEmits(expr) ||
processWithDefaults(expr)
) {
s.remove(node.start! + startOffset, node.end! + startOffset)
} else if (processDefineExpose(node.expression)) {
} else if (processDefineExpose(expr)) {
// defineExpose({}) -> expose({})
const callee = (node.expression as CallExpression).callee
const callee = (expr as CallExpression).callee
s.overwrite(
callee.start! + startOffset,
callee.end! + startOffset,
Expand All @@ -1207,12 +1209,13 @@ export function compileScript(
let left = total
for (let i = 0; i < total; i++) {
const decl = node.declarations[i]
if (decl.init) {
const init = decl.init && unwrapTSNode(decl.init)
if (init) {
// defineProps / defineEmits
const isDefineProps =
processDefineProps(decl.init, decl.id, node.kind) ||
processWithDefaults(decl.init, decl.id, node.kind)
const isDefineEmits = processDefineEmits(decl.init, decl.id)
processDefineProps(init, decl.id, node.kind) ||
processWithDefaults(init, decl.id, node.kind)
const isDefineEmits = processDefineEmits(init, decl.id)
if (isDefineProps || isDefineEmits) {
if (left === 1) {
s.remove(node.start! + startOffset, node.end! + startOffset)
Expand Down Expand Up @@ -1721,7 +1724,8 @@ function walkDeclaration(
if (node.type === 'VariableDeclaration') {
const isConst = node.kind === 'const'
// export const foo = ...
for (const { id, init } of node.declarations) {
for (const { id, init: _init } of node.declarations) {
const init = _init && unwrapTSNode(_init)
const isDefineCall = !!(
isConst &&
isCallOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,15 @@ const props = defineProps<{msg: string; ids?: string[]}>()
let ids = _ref([])"
`;
exports[`should unwrap TS node 1`] = `
"import { ref as _ref } from 'vue'
const bar = (ref(1))! as number
const baz = (bar)! as Ref<number>
const qux = (<number>_ref(10)!)
"
`;
exports[`using ref binding in property shorthand 1`] = `
"import { ref as _ref } from 'vue'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,18 @@ test('should not overwrite current scope', () => {
assertCode(code)
})

test('should unwrap TS node', () => {
const { code } = transform(
`
const bar = $(ref(1))! as number
const baz = $$(bar)! as Ref<number>
const qux = (<number>$ref(10)!)
`,
{ filename: 'foo.ts' }
)
assertCode(code)
})

describe('errors', () => {
test('$ref w/ destructure', () => {
expect(() => transform(`let { a } = $ref(1)`)).toThrow(
Expand Down
28 changes: 7 additions & 21 deletions packages/reactivity-transform/src/reactivityTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import {
isInDestructureAssignment,
isReferencedIdentifier,
isStaticProperty,
walkFunctionParams
unwrapTSNode,
walkFunctionParams,
TS_NODE_TYPES
} from '@vue/compiler-core'
import { parse, ParserPlugin } from '@babel/parser'
import { hasOwn, isArray, isString, genPropsAccessExp } from '@vue/shared'
Expand Down Expand Up @@ -261,25 +263,11 @@ export function transformAST(
return s.original.slice(node.start! + offset, node.end! + offset)
}

const WRAPPER_NODE_TYPES = [
'ParenthesizedExpression', // (foo)
'TSNonNullExpression', // foo!
'TSAsExpression', // foo as number
'TSTypeAssertion', // (<number>foo)
'TSInstantiationExpression' // foo<string>
]
function findUpParent() {
return parentStack
.slice()
.reverse()
.find(({ type }) => !WRAPPER_NODE_TYPES.includes(type))
}
function unwrapNode(node: Node): Node {
if (WRAPPER_NODE_TYPES.includes(node.type)) {
return unwrapNode((node as any).expression)
} else {
return node
}
.find(({ type }) => !TS_NODE_TYPES.includes(type))
}

function walkScope(node: Program | BlockStatement, isRoot = false) {
Expand Down Expand Up @@ -318,7 +306,7 @@ export function transformAST(
}
for (const decl of stmt.declarations) {
let refCall
const init = decl.init ? unwrapNode(decl.init) : null
const init = decl.init ? unwrapTSNode(decl.init) : null
const isCall =
init &&
init.type === 'CallExpression' &&
Expand All @@ -327,7 +315,7 @@ export function transformAST(
processRefDeclaration(refCall, decl.id, init, stmt.kind === 'const')
} else {
const isProps =
isRoot && isCall && (decl as any).init.callee.name === 'defineProps'
isRoot && isCall && (init.callee as Identifier).name === 'defineProps'
for (const id of extractIdentifiers(decl.id)) {
if (isProps) {
// for defineProps destructure, only exclude them since they
Expand Down Expand Up @@ -677,7 +665,7 @@ export function transformAST(
if (
parent &&
parent.type.startsWith('TS') &&
!WRAPPER_NODE_TYPES.includes(parent.type)
!TS_NODE_TYPES.includes(parent.type)
) {
return this.skip()
}
Expand Down Expand Up @@ -775,8 +763,6 @@ export function transformAST(
}
})

console.log(s.toString())

return {
rootRefs: Object.keys(rootScope).filter(key => {
const binding = rootScope[key]
Expand Down

0 comments on commit d8f131a

Please sign in to comment.