refactor(types): mark more internal APIs

This commit is contained in:
Evan You 2020-05-01 10:37:40 -04:00
parent 22717772dd
commit 68e1ce8b66
7 changed files with 232 additions and 71 deletions

View File

@ -1,6 +1,6 @@
import { HMRRuntime } from '../src/hmr' import { HMRRuntime } from '../src/hmr'
import '../src/hmr' import '../src/hmr'
import { ComponentOptions, RenderFunction } from '../src/component' import { ComponentOptions, InternalRenderFunction } from '../src/component'
import { import {
render, render,
nodeOps, nodeOps,
@ -18,7 +18,9 @@ const { createRecord, rerender, reload } = __VUE_HMR_RUNTIME__
function compileToFunction(template: string) { function compileToFunction(template: string) {
const { code } = baseCompile(template) const { code } = baseCompile(template)
const render = new Function('Vue', code)(runtimeTest) as RenderFunction const render = new Function('Vue', code)(
runtimeTest
) as InternalRenderFunction
render._rc = true // isRuntimeCompiled render._rc = true // isRuntimeCompiled
return render return render
} }

View File

@ -3,9 +3,10 @@ import {
MethodOptions, MethodOptions,
ComponentOptionsWithoutProps, ComponentOptionsWithoutProps,
ComponentOptionsWithArrayProps, ComponentOptionsWithArrayProps,
ComponentOptionsWithObjectProps ComponentOptionsWithObjectProps,
RenderFunction
} from './componentOptions' } from './componentOptions'
import { SetupContext, RenderFunction, FunctionalComponent } from './component' import { SetupContext, FunctionalComponent } from './component'
import { ComponentPublicInstance } from './componentProxy' import { ComponentPublicInstance } from './componentProxy'
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
import { EmitsOptions } from './componentEmits' import { EmitsOptions } from './componentEmits'

View File

@ -47,11 +47,28 @@ import { startMeasure, endMeasure } from './profiling'
export type Data = { [key: string]: unknown } export type Data = { [key: string]: unknown }
// Note: can't mark this whole interface internal because some public interfaces
// extend it.
export interface SFCInternalOptions { export interface SFCInternalOptions {
/**
* @internal
*/
__scopeId?: string __scopeId?: string
/**
* @internal
*/
__cssModules?: Data __cssModules?: Data
/**
* @internal
*/
__hmrId?: string __hmrId?: string
/**
* @internal
*/
__hmrUpdated?: boolean __hmrUpdated?: boolean
/**
* This one should be exposed so that devtools can make use of it
*/
__file?: string __file?: string
} }
@ -59,6 +76,7 @@ export interface FunctionalComponent<
P = {}, P = {},
E extends EmitsOptions = Record<string, any> E extends EmitsOptions = Record<string, any>
> extends SFCInternalOptions { > extends SFCInternalOptions {
// use of any here is intentional so it can be a valid JSX Element constructor
(props: P, ctx: SetupContext<E>): any (props: P, ctx: SetupContext<E>): any
props?: ComponentPropsOptions<P> props?: ComponentPropsOptions<P>
emits?: E | (keyof E)[] emits?: E | (keyof E)[]
@ -105,7 +123,10 @@ export interface SetupContext<E = ObjectEmitsOptions> {
emit: EmitFn<E> emit: EmitFn<E>
} }
export type RenderFunction = { /**
* @internal
*/
export type InternalRenderFunction = {
( (
ctx: ComponentPublicInstance, ctx: ComponentPublicInstance,
cache: ComponentInternalInstance['renderCache'] cache: ComponentInternalInstance['renderCache']
@ -113,39 +134,89 @@ export type RenderFunction = {
_rc?: boolean // isRuntimeCompiled _rc?: boolean // isRuntimeCompiled
} }
/**
* We expose a subset of properties on the internal instance as they are
* useful for advanced external libraries and tools.
*/
export interface ComponentInternalInstance { export interface ComponentInternalInstance {
uid: number uid: number
type: Component type: Component
parent: ComponentInternalInstance | null parent: ComponentInternalInstance | null
appContext: AppContext
root: ComponentInternalInstance root: ComponentInternalInstance
appContext: AppContext
/**
* Vnode representing this component in its parent's vdom tree
*/
vnode: VNode vnode: VNode
/**
* The pending new vnode from parent updates
* @internal
*/
next: VNode | null next: VNode | null
/**
* Root vnode of this component's own vdom tree
*/
subTree: VNode subTree: VNode
/**
* The reactive effect for rendering and patching the component. Callable.
*/
update: ReactiveEffect update: ReactiveEffect
render: RenderFunction | null /**
effects: ReactiveEffect[] | null * The render function that returns vdom tree.
* @internal
*/
render: InternalRenderFunction | null
/**
* Object containing values this component provides for its descendents
* @internal
*/
provides: Data provides: Data
// cache for proxy access type to avoid hasOwnProperty calls /**
* Tracking reactive effects (e.g. watchers) associated with this component
* so that they can be automatically stopped on component unmount
* @internal
*/
effects: ReactiveEffect[] | null
/**
* cache for proxy access type to avoid hasOwnProperty calls
* @internal
*/
accessCache: Data | null accessCache: Data | null
// cache for render function values that rely on _ctx but won't need updates /**
// after initialized (e.g. inline handlers) * cache for render function values that rely on _ctx but won't need updates
* after initialized (e.g. inline handlers)
* @internal
*/
renderCache: (Function | VNode)[] renderCache: (Function | VNode)[]
// assets for fast resolution /**
* Asset hashes that prototypally inherits app-level asset hashes for fast
* resolution
* @internal
*/
components: Record<string, Component> components: Record<string, Component>
/**
* @internal
*/
directives: Record<string, Directive> directives: Record<string, Directive>
// the rest are only for stateful components --------------------------------- // the rest are only for stateful components ---------------------------------
// main proxy that serves as the public instance (`this`) // main proxy that serves as the public instance (`this`)
proxy: ComponentPublicInstance | null proxy: ComponentPublicInstance | null
// alternative proxy used only for runtime-compiled render functions using
// `with` block /**
* alternative proxy used only for runtime-compiled render functions using
* `with` block
* @internal
*/
withProxy: ComponentPublicInstance | null withProxy: ComponentPublicInstance | null
// This is the target for the public instance proxy. It also holds properties /**
// injected by user options (computed, methods etc.) and user-attached * This is the target for the public instance proxy. It also holds properties
// custom properties (via `this.x = ...`) * injected by user options (computed, methods etc.) and user-attached
* custom properties (via `this.x = ...`)
* @internal
*/
ctx: Data ctx: Data
// internal state // internal state
@ -156,34 +227,91 @@ export interface ComponentInternalInstance {
refs: Data refs: Data
emit: EmitFn emit: EmitFn
// setup /**
* setup related
* @internal
*/
setupState: Data setupState: Data
/**
* @internal
*/
setupContext: SetupContext | null setupContext: SetupContext | null
// suspense related /**
* suspense related
* @internal
*/
suspense: SuspenseBoundary | null suspense: SuspenseBoundary | null
/**
* @internal
*/
asyncDep: Promise<any> | null asyncDep: Promise<any> | null
/**
* @internal
*/
asyncResolved: boolean asyncResolved: boolean
// lifecycle // lifecycle
isMounted: boolean isMounted: boolean
isUnmounted: boolean isUnmounted: boolean
isDeactivated: boolean isDeactivated: boolean
/**
* @internal
*/
[LifecycleHooks.BEFORE_CREATE]: LifecycleHook [LifecycleHooks.BEFORE_CREATE]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.CREATED]: LifecycleHook [LifecycleHooks.CREATED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.BEFORE_MOUNT]: LifecycleHook [LifecycleHooks.BEFORE_MOUNT]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.MOUNTED]: LifecycleHook [LifecycleHooks.MOUNTED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.BEFORE_UPDATE]: LifecycleHook [LifecycleHooks.BEFORE_UPDATE]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.UPDATED]: LifecycleHook [LifecycleHooks.UPDATED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.BEFORE_UNMOUNT]: LifecycleHook [LifecycleHooks.BEFORE_UNMOUNT]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.UNMOUNTED]: LifecycleHook [LifecycleHooks.UNMOUNTED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.RENDER_TRACKED]: LifecycleHook [LifecycleHooks.RENDER_TRACKED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.RENDER_TRIGGERED]: LifecycleHook [LifecycleHooks.RENDER_TRIGGERED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.ACTIVATED]: LifecycleHook [LifecycleHooks.ACTIVATED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.DEACTIVATED]: LifecycleHook [LifecycleHooks.DEACTIVATED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.ERROR_CAPTURED]: LifecycleHook [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
// hmr marker (dev only) /**
* hmr marker (dev only)
* @internal
*/
renderUpdated?: boolean renderUpdated?: boolean
} }
@ -386,7 +514,7 @@ export function handleSetupResult(
) { ) {
if (isFunction(setupResult)) { if (isFunction(setupResult)) {
// setup returned an inline render function // setup returned an inline render function
instance.render = setupResult as RenderFunction instance.render = setupResult as InternalRenderFunction
} else if (isObject(setupResult)) { } else if (isObject(setupResult)) {
if (__DEV__ && isVNode(setupResult)) { if (__DEV__ && isVNode(setupResult)) {
warn( warn(
@ -413,7 +541,7 @@ export function handleSetupResult(
type CompileFunction = ( type CompileFunction = (
template: string | object, template: string | object,
options?: CompilerOptions options?: CompilerOptions
) => RenderFunction ) => InternalRenderFunction
let compile: CompileFunction | undefined let compile: CompileFunction | undefined
@ -435,7 +563,7 @@ function finishComponentSetup(
// template / render function normalization // template / render function normalization
if (__NODE_JS__ && isSSR) { if (__NODE_JS__ && isSSR) {
if (Component.render) { if (Component.render) {
instance.render = Component.render as RenderFunction instance.render = Component.render as InternalRenderFunction
} }
} else if (!instance.render) { } else if (!instance.render) {
if (compile && Component.template && !Component.render) { if (compile && Component.template && !Component.render) {
@ -449,7 +577,7 @@ function finishComponentSetup(
endMeasure(instance, `compile`) endMeasure(instance, `compile`)
} }
// mark the function as runtime compiled // mark the function as runtime compiled
;(Component.render as RenderFunction)._rc = true ;(Component.render as InternalRenderFunction)._rc = true
} }
if (__DEV__ && !Component.render) { if (__DEV__ && !Component.render) {
@ -471,7 +599,7 @@ function finishComponentSetup(
} }
} }
instance.render = (Component.render || NOOP) as RenderFunction instance.render = (Component.render || NOOP) as InternalRenderFunction
// for runtime-compiled render functions using `with` blocks, the render // for runtime-compiled render functions using `with` blocks, the render
// proxy used needs a different `has` handler which is more performant and // proxy used needs a different `has` handler which is more performant and

View File

@ -2,7 +2,6 @@ import {
ComponentInternalInstance, ComponentInternalInstance,
Data, Data,
SetupContext, SetupContext,
RenderFunction,
SFCInternalOptions, SFCInternalOptions,
PublicAPIComponent, PublicAPIComponent,
Component Component
@ -51,6 +50,7 @@ import { EmitsOptions } from './componentEmits'
import { Directive } from './directives' import { Directive } from './directives'
import { ComponentPublicInstance } from './componentProxy' import { ComponentPublicInstance } from './componentProxy'
import { warn } from './warning' import { warn } from './warning'
import { VNodeChild } from './vnode'
/** /**
* Interface for declaring custom options. * Interface for declaring custom options.
@ -70,6 +70,8 @@ import { warn } from './warning'
*/ */
export interface ComponentCustomOptions {} export interface ComponentCustomOptions {}
export type RenderFunction = () => VNodeChild
export interface ComponentOptionsBase< export interface ComponentOptionsBase<
Props, Props,
RawBindings, RawBindings,
@ -95,13 +97,6 @@ export interface ComponentOptionsBase<
// Luckily `render()` doesn't need any arguments nor does it care about return // Luckily `render()` doesn't need any arguments nor does it care about return
// type. // type.
render?: Function render?: Function
// SSR only. This is produced by compiler-ssr and attached in compiler-sfc
// not user facing, so the typing is lax and for test only.
ssrRender?: (
ctx: any,
push: (item: any) => void,
parentInstance: ComponentInternalInstance
) => void
components?: Record<string, PublicAPIComponent> components?: Record<string, PublicAPIComponent>
directives?: Record<string, Directive> directives?: Record<string, Directive>
inheritAttrs?: boolean inheritAttrs?: boolean
@ -109,11 +104,34 @@ export interface ComponentOptionsBase<
// Internal ------------------------------------------------------------------ // Internal ------------------------------------------------------------------
// marker for AsyncComponentWrapper /**
* SSR only. This is produced by compiler-ssr and attached in compiler-sfc
* not user facing, so the typing is lax and for test only.
*
* @internal
*/
ssrRender?: (
ctx: any,
push: (item: any) => void,
parentInstance: ComponentInternalInstance
) => void
/**
* marker for AsyncComponentWrapper
* @internal
*/
__asyncLoader?: () => Promise<Component> __asyncLoader?: () => Promise<Component>
// cache for merged $options /**
* cache for merged $options
* @internal
*/
__merged?: ComponentOptions __merged?: ComponentOptions
// Type differentiators ------------------------------------------------------
// Note these are internal but need to be exposed in d.ts for type inference
// to work!
// type-only differentiator to separate OptionWithoutProps from a constructor // type-only differentiator to separate OptionWithoutProps from a constructor
// type returned by defineComponent() or FunctionalComponent // type returned by defineComponent() or FunctionalComponent
call?: never call?: never

View File

@ -1,7 +1,7 @@
import { import {
ComponentInternalInstance, ComponentInternalInstance,
ComponentOptions, ComponentOptions,
RenderFunction InternalRenderFunction
} from './component' } from './component'
import { queueJob, queuePostFlushCb } from './scheduler' import { queueJob, queuePostFlushCb } from './scheduler'
@ -65,14 +65,14 @@ function createRecord(id: string, comp: ComponentOptions): boolean {
return true return true
} }
function rerender(id: string, newRender?: RenderFunction) { function rerender(id: string, newRender?: Function) {
const record = map.get(id) const record = map.get(id)
if (!record) return if (!record) return
// Array.from creates a snapshot which avoids the set being mutated during // Array.from creates a snapshot which avoids the set being mutated during
// updates // updates
Array.from(record.instances).forEach(instance => { Array.from(record.instances).forEach(instance => {
if (newRender) { if (newRender) {
instance.render = newRender instance.render = newRender as InternalRenderFunction
} }
instance.renderCache = [] instance.renderCache = []
// this flag forces child components with slot content to update // this flag forces child components with slot content to update

View File

@ -1,4 +1,4 @@
// Public API ------------------------------------------------------------------ // Core API ------------------------------------------------------------------
export const version = __VERSION__ export const version = __VERSION__
export { export {
@ -51,15 +51,11 @@ export { getCurrentInstance } from './component'
// For raw render function users // For raw render function users
export { h } from './h' export { h } from './h'
export { // Advanced render function utilities
createVNode, export { createVNode, cloneVNode, mergeProps } from './vnode'
cloneVNode, // VNode types
mergeProps, export { Fragment, Text, Comment, Static } from './vnode'
openBlock, // Built-in components
createBlock
} from './vnode'
// Internal Components
export { Text, Comment, Fragment } from './vnode'
export { Teleport, TeleportProps } from './components/Teleport' export { Teleport, TeleportProps } from './components/Teleport'
export { Suspense, SuspenseProps } from './components/Suspense' export { Suspense, SuspenseProps } from './components/Suspense'
export { KeepAlive, KeepAliveProps } from './components/KeepAlive' export { KeepAlive, KeepAliveProps } from './components/KeepAlive'
@ -67,10 +63,8 @@ export {
BaseTransition, BaseTransition,
BaseTransitionProps BaseTransitionProps
} from './components/BaseTransition' } from './components/BaseTransition'
// SFC CSS Modules // SFC CSS Modules
export { useCSSModule } from './helpers/useCssModule' export { useCSSModule } from './helpers/useCssModule'
// SSR context // SSR context
export { useSSRContext, ssrContextKey } from './helpers/useSsrContext' export { useSSRContext, ssrContextKey } from './helpers/useSsrContext'
@ -125,6 +119,7 @@ export {
} from './apiCreateApp' } from './apiCreateApp'
export { export {
VNode, VNode,
VNodeChild,
VNodeTypes, VNodeTypes,
VNodeProps, VNodeProps,
VNodeArrayChildren, VNodeArrayChildren,
@ -134,7 +129,6 @@ export {
Component, Component,
FunctionalComponent, FunctionalComponent,
ComponentInternalInstance, ComponentInternalInstance,
RenderFunction,
SetupContext SetupContext
} from './component' } from './component'
export { export {
@ -143,7 +137,8 @@ export {
ComponentOptionsWithObjectProps, ComponentOptionsWithObjectProps,
ComponentOptionsWithArrayProps, ComponentOptionsWithArrayProps,
ComponentCustomOptions, ComponentCustomOptions,
ComponentOptionsBase ComponentOptionsBase,
RenderFunction
} from './componentOptions' } from './componentOptions'
export { export {
ComponentPublicInstance, ComponentPublicInstance,
@ -202,6 +197,8 @@ export { renderSlot } from './helpers/renderSlot'
export { createSlots } from './helpers/createSlots' export { createSlots } from './helpers/createSlots'
export { pushScopeId, popScopeId, withScopeId } from './helpers/scopeId' export { pushScopeId, popScopeId, withScopeId } from './helpers/scopeId'
export { export {
openBlock,
createBlock,
setBlockTracking, setBlockTracking,
createTextVNode, createTextVNode,
createCommentVNode, createCommentVNode,

View File

@ -82,12 +82,17 @@ export interface VNodeProps {
onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[] onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[]
} }
type VNodeChildAtom = VNode | string | number | boolean | null | void type VNodeChildAtom =
| VNode
| string
| number
| boolean
| null
| undefined
| void
export interface VNodeArrayChildren< export interface VNodeArrayChildren
HostNode = RendererNode, extends Array<VNodeArrayChildren | VNodeChildAtom> {}
HostElement = RendererElement
> extends Array<VNodeArrayChildren | VNodeChildAtom> {}
export type VNodeChild = VNodeChildAtom | VNodeArrayChildren export type VNodeChild = VNodeChildAtom | VNodeArrayChildren
@ -134,17 +139,22 @@ export interface VNode<HostNode = RendererNode, HostElement = RendererElement> {
const blockStack: (VNode[] | null)[] = [] const blockStack: (VNode[] | null)[] = []
let currentBlock: VNode[] | null = null let currentBlock: VNode[] | null = null
// Open a block. /**
// This must be called before `createBlock`. It cannot be part of `createBlock` * Open a block.
// because the children of the block are evaluated before `createBlock` itself * This must be called before `createBlock`. It cannot be part of `createBlock`
// is called. The generated code typically looks like this: * because the children of the block are evaluated before `createBlock` itself
// * is called. The generated code typically looks like this:
// function render() { *
// return (openBlock(),createBlock('div', null, [...])) * ```js
// } * function render() {
// * return (openBlock(),createBlock('div', null, [...]))
// disableTracking is true when creating a fragment block, since a fragment * }
// always diffs its children. * ```
* disableTracking is true when creating a fragment block, since a fragment
* always diffs its children.
*
* @internal
*/
export function openBlock(disableTracking = false) { export function openBlock(disableTracking = false) {
blockStack.push((currentBlock = disableTracking ? null : [])) blockStack.push((currentBlock = disableTracking ? null : []))
} }
@ -168,15 +178,20 @@ let shouldTrack = 1
* _cache[1] * _cache[1]
* ) * )
* ``` * ```
*
* @internal * @internal
*/ */
export function setBlockTracking(value: number) { export function setBlockTracking(value: number) {
shouldTrack += value shouldTrack += value
} }
// Create a block root vnode. Takes the same exact arguments as `createVNode`. /**
// A block root keeps track of dynamic nodes within the block in the * Create a block root vnode. Takes the same exact arguments as `createVNode`.
// `dynamicChildren` array. * A block root keeps track of dynamic nodes within the block in the
* `dynamicChildren` array.
*
* @internal
*/
export function createBlock( export function createBlock(
type: VNodeTypes | ClassComponent, type: VNodeTypes | ClassComponent,
props?: { [key: string]: any } | null, props?: { [key: string]: any } | null,