Procházet zdrojové kódy

types: (wip) improve dts output

Evan You před 6 roky
rodič
revize
5eee1152ca

+ 3 - 2
packages/compiler-core/src/transforms/vFor.ts

@@ -16,7 +16,8 @@ import {
   createObjectProperty,
   ForCodegenNode,
   ElementCodegenNode,
-  SlotOutletCodegenNode
+  SlotOutletCodegenNode,
+  SlotOutletNode
 } from '../ast'
 import { createCompilerError, ErrorCodes } from '../errors'
 import {
@@ -119,7 +120,7 @@ export const transformFor = createStructuralDirectiveTransform(
         : isTemplate &&
           node.children.length === 1 &&
           isSlotOutlet(node.children[0])
-          ? node.children[0]
+          ? (node.children[0] as SlotOutletNode) // api-extractor somehow fails to infer this
           : null
       const keyProperty = keyProp
         ? createObjectProperty(

+ 13 - 8
packages/compiler-core/src/utils.ts

@@ -190,18 +190,23 @@ export function createBlockExpression(
   ])
 }
 
-export const isVSlot = (p: ElementNode['props'][0]): p is DirectiveNode =>
-  p.type === NodeTypes.DIRECTIVE && p.name === 'slot'
+export function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode {
+  return p.type === NodeTypes.DIRECTIVE && p.name === 'slot'
+}
 
-export const isTemplateNode = (
+export function isTemplateNode(
   node: RootNode | TemplateChildNode
-): node is TemplateNode =>
-  node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE
+): node is TemplateNode {
+  return (
+    node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE
+  )
+}
 
-export const isSlotOutlet = (
+export function isSlotOutlet(
   node: RootNode | TemplateChildNode
-): node is SlotOutletNode =>
-  node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
+): node is SlotOutletNode {
+  return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
+}
 
 export function injectProp(
   node: ElementCodegenNode | ComponentCodegenNode | SlotOutletCodegenNode,

+ 2 - 8
packages/runtime-core/src/componentSlots.ts

@@ -1,16 +1,10 @@
 import { ComponentInternalInstance, currentInstance } from './component'
-import {
-  VNode,
-  NormalizedChildren,
-  normalizeVNode,
-  VNodeChild,
-  VNodeChildren
-} from './vnode'
+import { VNode, NormalizedChildren, normalizeVNode, VNodeChild } from './vnode'
 import { isArray, isFunction } from '@vue/shared'
 import { ShapeFlags } from './shapeFlags'
 import { warn } from './warning'
 
-export type Slot = (...args: any[]) => VNodeChildren
+export type Slot = (...args: any[]) => VNode[]
 
 export type InternalSlots = {
   [name: string]: Slot

+ 1 - 1
packages/runtime-core/src/index.ts

@@ -30,7 +30,7 @@ export { PublicPatchFlags as PatchFlags } from '@vue/shared'
 export { getCurrentInstance } from './component'
 
 // For custom renderers
-export { createRenderer } from './createRenderer'
+export { createRenderer, RootRenderFunction } from './createRenderer'
 export { warn } from './warning'
 export {
   handleError,

+ 1 - 1
packages/runtime-core/src/keepAlive.ts

@@ -135,7 +135,7 @@ export const KeepAlive = {
 
     return () => {
       if (!slots.default) {
-        return
+        return null
       }
 
       const children = slots.default()

+ 6 - 3
packages/runtime-core/src/vnode.ts

@@ -25,9 +25,12 @@ export const Portal = Symbol(__DEV__ ? 'Portal' : undefined)
 export const Text = Symbol(__DEV__ ? 'Text' : undefined)
 export const Comment = Symbol(__DEV__ ? 'Comment' : undefined)
 
-const Suspense = (__FEATURE_SUSPENSE__
-  ? SuspenseImpl
-  : null) as typeof SuspenseImpl
+// Export as {} to avoid circular type dependency between `suspense.ts` and
+// `createRenderer.ts` in exported types.
+// A circular type dependency causes tsc to generate d.ts with dynmaic import()
+// calls using realtive paths, which works for separate d.ts files, but will
+// fail after d.ts rollup with API Extractor.
+const Suspense = (__FEATURE_SUSPENSE__ ? SuspenseImpl : null) as {}
 export { Suspense }
 
 export type VNodeTypes =

+ 2 - 1
packages/runtime-dom/package.json

@@ -13,7 +13,8 @@
   "sideEffects": false,
   "buildOptions": {
     "name": "VueDOMRuntime",
-    "formats": ["esm", "cjs", "global", "esm-browser"]
+    "formats": ["esm", "cjs", "global", "esm-browser"],
+    "dts": ["jsx.d.ts"]
   },
   "repository": {
     "type": "git",

+ 11 - 5
packages/runtime-dom/src/index.ts

@@ -1,16 +1,24 @@
-import { createRenderer, warn } from '@vue/runtime-core'
+import {
+  createRenderer,
+  warn,
+  App,
+  RootRenderFunction
+} from '@vue/runtime-core'
 import { nodeOps } from './nodeOps'
 import { patchProp } from './patchProp'
 // Importing from the compiler, will be tree-shaken in prod
 import { isHTMLTag, isSVGTag } from '@vue/compiler-dom'
 import { isFunction, isString } from '@vue/shared'
 
-const { render, createApp: baseCreateApp } = createRenderer<Node, Element>({
+const { render: baseRender, createApp: baseCreateApp } = createRenderer({
   patchProp,
   ...nodeOps
 })
 
-const createApp = () => {
+// use explicit type casts here to avoid import() calls in rolled-up d.ts
+export const render = baseRender as RootRenderFunction<Node, Element>
+
+export const createApp = (): App<Element> => {
   const app = baseCreateApp()
 
   if (__DEV__) {
@@ -48,8 +56,6 @@ const createApp = () => {
   return app
 }
 
-export { render, createApp }
-
 // DOM-only runtime helpers
 export {
   vModelText,

+ 14 - 2
scripts/build.js

@@ -27,6 +27,7 @@ const targets = args._
 const formats = args.formats || args.f
 const devOnly = args.devOnly || args.d
 const prodOnly = !devOnly && (args.prodOnly || args.p)
+const buildTypes = args.t || args.types
 const buildAllMatching = args.all || args.a
 const lean = args.lean || args.l
 const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7)
@@ -68,7 +69,7 @@ async function build(target) {
         `NODE_ENV:${env}`,
         `TARGET:${target}`,
         formats ? `FORMATS:${formats}` : ``,
-        args.types ? `TYPES:true` : ``,
+        buildTypes ? `TYPES:true` : ``,
         prodOnly ? `PROD_ONLY:true` : ``,
         lean ? `LEAN:true` : ``
       ]
@@ -78,7 +79,7 @@ async function build(target) {
     { stdio: 'inherit' }
   )
 
-  if (args.types && pkg.types) {
+  if (buildTypes && pkg.types) {
     console.log()
     console.log(
       chalk.bold(chalk.yellow(`Rolling up type definitions for ${target}...`))
@@ -97,6 +98,17 @@ async function build(target) {
     })
 
     if (result.succeeded) {
+      // concat additional d.ts to rolled-up dts (mostly for JSX)
+      if (pkg.buildOptions.dts) {
+        const dtsPath = path.resolve(pkgDir, pkg.types)
+        const existing = await fs.readFile(dtsPath, 'utf-8')
+        const toAdd = await Promise.all(
+          pkg.buildOptions.dts.map(file => {
+            return fs.readFile(path.resolve(pkgDir, file), 'utf-8')
+          })
+        )
+        await fs.writeFile(dtsPath, existing + '\n' + toAdd.join('\n'))
+      }
       console.log(
         chalk.bold(chalk.green(`API Extractor completed successfully.`))
       )