]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: adjust ResolvedElements shape
authorEvan You <yyx990803@gmail.com>
Thu, 13 Apr 2023 02:42:15 +0000 (10:42 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 13 Apr 2023 02:42:15 +0000 (10:42 +0800)
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
packages/compiler-sfc/src/script/defineEmits.ts
packages/compiler-sfc/src/script/defineProps.ts
packages/compiler-sfc/src/script/resolveType.ts

index 3e61e1b231a9480f83042c7745f46409a606c5a7..5d5a424f26bcaea479cf84b96793776735343b83 100644 (file)
@@ -8,19 +8,19 @@ import {
 
 describe('resolveType', () => {
   test('type literal', () => {
-    const { elements, callSignatures } = resolve(`type Target = {
+    const { props, calls } = resolve(`type Target = {
       foo: number // property
       bar(): void // method
       'baz': string // string literal key
       (e: 'foo'): void // call signature
       (e: 'bar'): void
     }`)
-    expect(elements).toStrictEqual({
+    expect(props).toStrictEqual({
       foo: ['Number'],
       bar: ['Function'],
       baz: ['String']
     })
-    expect(callSignatures?.length).toBe(2)
+    expect(calls?.length).toBe(2)
   })
 
   test('reference type', () => {
@@ -28,7 +28,7 @@ describe('resolveType', () => {
       resolve(`
     type Aliased = { foo: number }
     type Target = Aliased
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['Number']
     })
@@ -39,7 +39,7 @@ describe('resolveType', () => {
       resolve(`
     export type Aliased = { foo: number }
     type Target = Aliased
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['Number']
     })
@@ -50,7 +50,7 @@ describe('resolveType', () => {
       resolve(`
     interface Aliased { foo: number }
     type Target = Aliased
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['Number']
     })
@@ -61,7 +61,7 @@ describe('resolveType', () => {
       resolve(`
     export interface Aliased { foo: number }
     type Target = Aliased
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['Number']
     })
@@ -75,7 +75,7 @@ describe('resolveType', () => {
     interface C { c: string }
     interface Aliased extends B, C { foo: number }
     type Target = Aliased
-    `).elements
+    `).props
     ).toStrictEqual({
       a: ['Function'],
       b: ['Boolean'],
@@ -88,7 +88,7 @@ describe('resolveType', () => {
     expect(
       resolve(`
     type Target = (e: 'foo') => void
-    `).callSignatures?.length
+    `).calls?.length
     ).toBe(1)
   })
 
@@ -97,7 +97,7 @@ describe('resolveType', () => {
       resolve(`
     type Fn = (e: 'foo') => void
     type Target = Fn
-    `).callSignatures?.length
+    `).calls?.length
     ).toBe(1)
   })
 
@@ -108,7 +108,7 @@ describe('resolveType', () => {
     type Bar = { bar: string }
     type Baz = { bar: string | boolean }
     type Target = { self: any } & Foo & Bar & Baz
-    `).elements
+    `).props
     ).toStrictEqual({
       self: ['Unknown'],
       foo: ['Number'],
@@ -138,7 +138,7 @@ describe('resolveType', () => {
         }
 
     type Target = CommonProps & ConditionalProps
-    `).elements
+    `).props
     ).toStrictEqual({
       size: ['String'],
       color: ['String', 'Number'],
@@ -155,7 +155,7 @@ describe('resolveType', () => {
     type Target = {
       [\`_\${T}_\${S}_\`]: string
     }
-    `).elements
+    `).props
     ).toStrictEqual({
       _foo_x_: ['String'],
       _foo_y_: ['String'],
@@ -177,7 +177,7 @@ describe('resolveType', () => {
     } & {
       [K in \`x\${T}\`]: string
     }
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['String', 'Number'],
       bar: ['String', 'Number'],
@@ -196,7 +196,7 @@ describe('resolveType', () => {
     type T = { foo: number, bar: string, baz: boolean }
     type K = 'foo' | 'bar'
     type Target = Pick<T, K>
-    `).elements
+    `).props
     ).toStrictEqual({
       foo: ['Number'],
       bar: ['String']
@@ -209,7 +209,7 @@ describe('resolveType', () => {
     type T = { foo: number, bar: string, baz: boolean }
     type K = 'foo' | 'bar'
     type Target = Omit<T, K>
-    `).elements
+    `).props
     ).toStrictEqual({
       baz: ['Boolean']
     })
@@ -231,13 +231,13 @@ function resolve(code: string) {
     s => s.type === 'TSTypeAliasDeclaration' && s.id.name === 'Target'
   ) as TSTypeAliasDeclaration
   const raw = resolveTypeElements(ctx, targetDecl.typeAnnotation)
-  const elements: Record<string, string[]> = {}
-  for (const key in raw) {
-    elements[key] = inferRuntimeType(ctx, raw[key])
+  const props: Record<string, string[]> = {}
+  for (const key in raw.props) {
+    props[key] = inferRuntimeType(ctx, raw.props[key])
   }
   return {
-    elements,
-    callSignatures: raw.__callSignatures,
+    props,
+    calls: raw.calls,
     raw
   }
 }
index 0e080b4fed44c19c1bd1c7952c5c0bc0bdd7f322..e615cd71a0dd87a2c25efa6f8c9c6db73cf4612e 100644 (file)
@@ -69,22 +69,22 @@ function extractRuntimeEmits(ctx: ScriptCompileContext): Set<string> {
     return emits
   }
 
-  const elements = resolveTypeElements(ctx, node)
+  const { props, calls } = resolveTypeElements(ctx, node)
 
   let hasProperty = false
-  for (const key in elements) {
+  for (const key in props) {
     emits.add(key)
     hasProperty = true
   }
 
-  if (elements.__callSignatures) {
+  if (calls) {
     if (hasProperty) {
       ctx.error(
         `defineEmits() type cannot mixed call signature and property syntax.`,
         node
       )
     }
-    for (const call of elements.__callSignatures) {
+    for (const call of calls) {
       extractEventNames(call.parameters[0], emits)
     }
   }
index ee8b5e55734e04f4cac0ec0c9da21c2328fb0532..16ea02fe3cf1383b2c0bbae82ba286763a11f512 100644 (file)
@@ -191,8 +191,8 @@ function resolveRuntimePropsFromType(
 ): PropTypeData[] {
   const props: PropTypeData[] = []
   const elements = resolveTypeElements(ctx, node)
-  for (const key in elements) {
-    const e = elements[key]
+  for (const key in elements.props) {
+    const e = elements.props[key]
     let type = inferRuntimeType(ctx, e)
     let skipCheck = false
     // skip check for result containing unknown types
index 0f6a4eb523036d48e05031a243a7712732ac79bb..ecd3838be7b5bc91f57a8d42cc2f97f2ca13d9e4 100644 (file)
@@ -18,7 +18,7 @@ import { UNKNOWN_TYPE } from './utils'
 import { ScriptCompileContext } from './context'
 import { ImportBinding } from '../compileScript'
 import { TSInterfaceDeclaration } from '@babel/types'
-import { capitalize, hasOwn, isArray } from '@vue/shared'
+import { capitalize, hasOwn } from '@vue/shared'
 import { Expression } from '@babel/types'
 
 export interface TypeScope {
@@ -28,11 +28,9 @@ export interface TypeScope {
   types: Record<string, Node>
 }
 
-type ResolvedElements = Record<
-  string,
-  TSPropertySignature | TSMethodSignature
-> & {
-  __callSignatures?: (TSCallSignatureDeclaration | TSFunctionType)[]
+interface ResolvedElements {
+  props: Record<string, TSPropertySignature | TSMethodSignature>
+  calls?: (TSCallSignatureDeclaration | TSFunctionType)[]
 }
 
 /**
@@ -62,9 +60,7 @@ function innerResolveTypeElements(
     case 'TSParenthesizedType':
       return resolveTypeElements(ctx, node.typeAnnotation)
     case 'TSFunctionType': {
-      const ret: ResolvedElements = {}
-      addCallSignature(ret, node)
-      return ret
+      return { props: {}, calls: [node] }
     }
     case 'TSExpressionWithTypeArguments': // referenced by interface extends
     case 'TSTypeReference': {
@@ -98,32 +94,11 @@ function innerResolveTypeElements(
   ctx.error(`Unsupported type in SFC macro: ${node.type}`, node)
 }
 
-function addCallSignature(
-  elements: ResolvedElements,
-  node:
-    | TSCallSignatureDeclaration
-    | TSFunctionType
-    | (TSCallSignatureDeclaration | TSFunctionType)[]
-) {
-  if (!elements.__callSignatures) {
-    Object.defineProperty(elements, '__callSignatures', {
-      enumerable: false,
-      value: isArray(node) ? node : [node]
-    })
-  } else {
-    if (isArray(node)) {
-      elements.__callSignatures.push(...node)
-    } else {
-      elements.__callSignatures.push(node)
-    }
-  }
-}
-
 function typeElementsToMap(
   ctx: ScriptCompileContext,
   elements: TSTypeElement[]
 ): ResolvedElements {
-  const ret: ResolvedElements = {}
+  const res: ResolvedElements = { props: {} }
   for (const e of elements) {
     if (e.type === 'TSPropertySignature' || e.type === 'TSMethodSignature') {
       const name =
@@ -133,10 +108,10 @@ function typeElementsToMap(
           ? e.key.value
           : null
       if (name && !e.computed) {
-        ret[name] = e
+        res.props[name] = e
       } else if (e.key.type === 'TemplateLiteral') {
         for (const key of resolveTemplateKeys(ctx, e.key)) {
-          ret[key] = e
+          res.props[key] = e
         }
       } else {
         ctx.error(
@@ -145,31 +120,32 @@ function typeElementsToMap(
         )
       }
     } else if (e.type === 'TSCallSignatureDeclaration') {
-      addCallSignature(ret, e)
+      ;(res.calls || (res.calls = [])).push(e)
     }
   }
-  return ret
+  return res
 }
 
 function mergeElements(
   maps: ResolvedElements[],
   type: 'TSUnionType' | 'TSIntersectionType'
 ): ResolvedElements {
-  const res: ResolvedElements = Object.create(null)
-  for (const m of maps) {
-    for (const key in m) {
-      if (!(key in res)) {
-        res[key] = m[key]
+  const res: ResolvedElements = { props: {} }
+  const { props: baseProps } = res
+  for (const { props, calls } of maps) {
+    for (const key in props) {
+      if (!hasOwn(baseProps, key)) {
+        baseProps[key] = props[key]
       } else {
-        res[key] = createProperty(res[key].key, {
+        baseProps[key] = createProperty(baseProps[key].key, {
           type,
           // @ts-ignore
-          types: [res[key], m[key]]
+          types: [baseProps[key], props[key]]
         })
       }
     }
-    if (m.__callSignatures) {
-      addCallSignature(res, m.__callSignatures)
+    if (calls) {
+      ;(res.calls || (res.calls = [])).push(...calls)
     }
   }
   return res
@@ -197,10 +173,10 @@ function resolveInterfaceMembers(
   const base = typeElementsToMap(ctx, node.body.body)
   if (node.extends) {
     for (const ext of node.extends) {
-      const resolvedExt = resolveTypeElements(ctx, ext)
-      for (const key in resolvedExt) {
-        if (!hasOwn(base, key)) {
-          base[key] = resolvedExt[key]
+      const { props } = resolveTypeElements(ctx, ext)
+      for (const key in props) {
+        if (!hasOwn(base.props, key)) {
+          base.props[key] = props[key]
         }
       }
     }
@@ -212,13 +188,13 @@ function resolveMappedType(
   ctx: ScriptCompileContext,
   node: TSMappedType
 ): ResolvedElements {
-  const res: ResolvedElements = {}
+  const res: ResolvedElements = { props: {} }
   if (!node.typeParameter.constraint) {
     ctx.error(`mapped type used in macros must have a finite constraint.`, node)
   }
   const keys = resolveStringType(ctx, node.typeParameter.constraint)
   for (const key of keys) {
-    res[key] = createProperty(
+    res.props[key] = createProperty(
       {
         type: 'Identifier',
         name: key
@@ -323,20 +299,18 @@ function resolveBuiltin(
       return t
     case 'Pick': {
       const picked = resolveStringType(ctx, node.typeParameters!.params[1])
-      const res: ResolvedElements = {}
-      if (t.__callSignatures) addCallSignature(res, t.__callSignatures)
+      const res: ResolvedElements = { props: {}, calls: t.calls }
       for (const key of picked) {
-        res[key] = t[key]
+        res.props[key] = t.props[key]
       }
       return res
     }
     case 'Omit':
       const omitted = resolveStringType(ctx, node.typeParameters!.params[1])
-      const res: ResolvedElements = {}
-      if (t.__callSignatures) addCallSignature(res, t.__callSignatures)
-      for (const key in t) {
+      const res: ResolvedElements = { props: {}, calls: t.calls }
+      for (const key in t.props) {
         if (!omitted.includes(key)) {
-          res[key] = t[key]
+          res.props[key] = t.props[key]
         }
       }
       return res