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 '../src/hmr'
import { ComponentOptions, RenderFunction } from '../src/component'
import { ComponentOptions, InternalRenderFunction } from '../src/component'
import {
render,
nodeOps,
@ -18,7 +18,9 @@ const { createRecord, rerender, reload } = __VUE_HMR_RUNTIME__
function compileToFunction(template: string) {
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
return render
}

View File

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

View File

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

View File

@ -2,7 +2,6 @@ import {
ComponentInternalInstance,
Data,
SetupContext,
RenderFunction,
SFCInternalOptions,
PublicAPIComponent,
Component
@ -51,6 +50,7 @@ import { EmitsOptions } from './componentEmits'
import { Directive } from './directives'
import { ComponentPublicInstance } from './componentProxy'
import { warn } from './warning'
import { VNodeChild } from './vnode'
/**
* Interface for declaring custom options.
@ -70,6 +70,8 @@ import { warn } from './warning'
*/
export interface ComponentCustomOptions {}
export type RenderFunction = () => VNodeChild
export interface ComponentOptionsBase<
Props,
RawBindings,
@ -95,13 +97,6 @@ export interface ComponentOptionsBase<
// Luckily `render()` doesn't need any arguments nor does it care about return
// type.
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>
directives?: Record<string, Directive>
inheritAttrs?: boolean
@ -109,11 +104,34 @@ export interface ComponentOptionsBase<
// 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>
// cache for merged $options
/**
* cache for merged $options
* @internal
*/
__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 returned by defineComponent() or FunctionalComponent
call?: never

View File

@ -1,7 +1,7 @@
import {
ComponentInternalInstance,
ComponentOptions,
RenderFunction
InternalRenderFunction
} from './component'
import { queueJob, queuePostFlushCb } from './scheduler'
@ -65,14 +65,14 @@ function createRecord(id: string, comp: ComponentOptions): boolean {
return true
}
function rerender(id: string, newRender?: RenderFunction) {
function rerender(id: string, newRender?: Function) {
const record = map.get(id)
if (!record) return
// Array.from creates a snapshot which avoids the set being mutated during
// updates
Array.from(record.instances).forEach(instance => {
if (newRender) {
instance.render = newRender
instance.render = newRender as InternalRenderFunction
}
instance.renderCache = []
// 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 {
@ -51,15 +51,11 @@ export { getCurrentInstance } from './component'
// For raw render function users
export { h } from './h'
export {
createVNode,
cloneVNode,
mergeProps,
openBlock,
createBlock
} from './vnode'
// Internal Components
export { Text, Comment, Fragment } from './vnode'
// Advanced render function utilities
export { createVNode, cloneVNode, mergeProps } from './vnode'
// VNode types
export { Fragment, Text, Comment, Static } from './vnode'
// Built-in components
export { Teleport, TeleportProps } from './components/Teleport'
export { Suspense, SuspenseProps } from './components/Suspense'
export { KeepAlive, KeepAliveProps } from './components/KeepAlive'
@ -67,10 +63,8 @@ export {
BaseTransition,
BaseTransitionProps
} from './components/BaseTransition'
// SFC CSS Modules
export { useCSSModule } from './helpers/useCssModule'
// SSR context
export { useSSRContext, ssrContextKey } from './helpers/useSsrContext'
@ -125,6 +119,7 @@ export {
} from './apiCreateApp'
export {
VNode,
VNodeChild,
VNodeTypes,
VNodeProps,
VNodeArrayChildren,
@ -134,7 +129,6 @@ export {
Component,
FunctionalComponent,
ComponentInternalInstance,
RenderFunction,
SetupContext
} from './component'
export {
@ -143,7 +137,8 @@ export {
ComponentOptionsWithObjectProps,
ComponentOptionsWithArrayProps,
ComponentCustomOptions,
ComponentOptionsBase
ComponentOptionsBase,
RenderFunction
} from './componentOptions'
export {
ComponentPublicInstance,
@ -202,6 +197,8 @@ export { renderSlot } from './helpers/renderSlot'
export { createSlots } from './helpers/createSlots'
export { pushScopeId, popScopeId, withScopeId } from './helpers/scopeId'
export {
openBlock,
createBlock,
setBlockTracking,
createTextVNode,
createCommentVNode,

View File

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