feat(compiler-sfc): expose type import deps on compiled script block

This commit is contained in:
Evan You 2023-04-15 18:06:48 +08:00
parent 075498c959
commit 8d8ddd686c
4 changed files with 60 additions and 49 deletions

View File

@ -264,81 +264,85 @@ describe('resolveType', () => {
}) })
describe('external type imports', () => { describe('external type imports', () => {
const files = {
'/foo.ts': 'export type P = { foo: number }',
'/bar.d.ts': 'type X = { bar: string }; export { X as Y }'
}
test('relative ts', () => { test('relative ts', () => {
expect( const { props, deps } = resolve(
resolve(
` `
import { P } from './foo' import { P } from './foo'
import { Y as PP } from './bar' import { Y as PP } from './bar'
defineProps<P & PP>() defineProps<P & PP>()
`, `,
{ files
'/foo.ts': 'export type P = { foo: number }', )
'/bar.d.ts': 'type X = { bar: string }; export { X as Y }' expect(props).toStrictEqual({
}
).props
).toStrictEqual({
foo: ['Number'], foo: ['Number'],
bar: ['String'] bar: ['String']
}) })
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
}) })
test('relative vue', () => { test('relative vue', () => {
expect( const files = {
resolve(
`
import { P } from './foo.vue'
import { P as PP } from './bar.vue'
defineProps<P & PP>()
`,
{
'/foo.vue': '/foo.vue':
'<script lang="ts">export type P = { foo: number }</script>', '<script lang="ts">export type P = { foo: number }</script>',
'/bar.vue': '/bar.vue':
'<script setup lang="tsx">export type P = { bar: string }</script>' '<script setup lang="tsx">export type P = { bar: string }</script>'
} }
).props const { props, deps } = resolve(
).toStrictEqual({ `
import { P } from './foo.vue'
import { P as PP } from './bar.vue'
defineProps<P & PP>()
`,
files
)
expect(props).toStrictEqual({
foo: ['Number'], foo: ['Number'],
bar: ['String'] bar: ['String']
}) })
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
}) })
test('relative (chained)', () => { test('relative (chained)', () => {
expect( const files = {
resolve(
`
import { P } from './foo'
defineProps<P>()
`,
{
'/foo.ts': `import type { P as PP } from './nested/bar.vue' '/foo.ts': `import type { P as PP } from './nested/bar.vue'
export type P = { foo: number } & PP`, export type P = { foo: number } & PP`,
'/nested/bar.vue': '/nested/bar.vue':
'<script setup lang="ts">export type P = { bar: string }</script>' '<script setup lang="ts">export type P = { bar: string }</script>'
} }
).props const { props, deps } = resolve(
).toStrictEqual({ `
import { P } from './foo'
defineProps<P>()
`,
files
)
expect(props).toStrictEqual({
foo: ['Number'], foo: ['Number'],
bar: ['String'] bar: ['String']
}) })
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
}) })
test('relative (chained, re-export)', () => { test('relative (chained, re-export)', () => {
expect( const files = {
resolve( '/foo.ts': `export { P as PP } from './bar'`,
'/bar.ts': 'export type P = { bar: string }'
}
const { props, deps } = resolve(
` `
import { PP as P } from './foo' import { PP as P } from './foo'
defineProps<P>() defineProps<P>()
`, `,
{ files
'/foo.ts': `export { P as PP } from './bar'`, )
'/bar.ts': 'export type P = { bar: string }' expect(props).toStrictEqual({
}
).props
).toStrictEqual({
bar: ['String'] bar: ['String']
}) })
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
}) })
test('ts module resolve', () => { test('ts module resolve', () => {
@ -357,7 +361,7 @@ describe('resolveType', () => {
'/pp.ts': 'export type PP = { bar: string }' '/pp.ts': 'export type PP = { bar: string }'
} }
const { props } = resolve( const { props, deps } = resolve(
` `
import { P } from 'foo' import { P } from 'foo'
import { PP } from 'bar' import { PP } from 'bar'
@ -370,6 +374,10 @@ describe('resolveType', () => {
foo: ['Number'], foo: ['Number'],
bar: ['String'] bar: ['String']
}) })
expect(deps && [...deps]).toStrictEqual([
'/node_modules/foo/index.d.ts',
'/pp.ts'
])
}) })
}) })
@ -447,6 +455,6 @@ function resolve(code: string, files: Record<string, string> = {}) {
return { return {
props, props,
calls: raw.calls, calls: raw.calls,
raw deps: ctx.deps
} }
} }

View File

@ -1035,7 +1035,8 @@ export function compileScript(
}) as unknown as RawSourceMap) }) as unknown as RawSourceMap)
: undefined, : undefined,
scriptAst: scriptAst?.body, scriptAst: scriptAst?.body,
scriptSetupAst: scriptSetupAst?.body scriptSetupAst: scriptSetupAst?.body,
deps: ctx.deps ? [...ctx.deps] : undefined
} }
} }

View File

@ -65,7 +65,7 @@ export class ScriptCompileContext {
/** /**
* to be exposed on compiled script block for HMR cache busting * to be exposed on compiled script block for HMR cache busting
*/ */
deps?: string[] deps?: Set<string>
constructor( constructor(
public descriptor: SFCDescriptor, public descriptor: SFCDescriptor,

View File

@ -547,7 +547,9 @@ function resolveTypeFromImport(
} }
if (resolved) { if (resolved) {
// TODO (hmr) register dependency file on ctx // (hmr) register dependency file on ctx
;(ctx.deps || (ctx.deps = new Set())).add(resolved)
return resolveTypeReference( return resolveTypeReference(
ctx, ctx,
node, node,