2019-09-12 03:44:37 +00:00
|
|
|
import { VNode, VNodeChild, isVNode } from './vnode'
|
2020-02-18 04:14:07 +00:00
|
|
|
import {
|
|
|
|
ReactiveEffect,
|
|
|
|
pauseTracking,
|
2020-04-15 03:49:46 +00:00
|
|
|
resetTracking,
|
2020-07-28 20:30:56 +00:00
|
|
|
shallowReadonly,
|
|
|
|
proxyRefs
|
2020-02-18 04:14:07 +00:00
|
|
|
} from '@vue/reactivity'
|
2019-09-06 16:58:31 +00:00
|
|
|
import {
|
2019-12-10 16:14:29 +00:00
|
|
|
ComponentPublicInstance,
|
2020-04-05 22:39:22 +00:00
|
|
|
PublicInstanceProxyHandlers,
|
|
|
|
RuntimeCompiledPublicInstanceProxyHandlers,
|
2020-04-16 16:49:50 +00:00
|
|
|
createRenderContext,
|
|
|
|
exposePropsOnRenderContext,
|
2020-08-19 20:11:29 +00:00
|
|
|
exposeSetupStateOnRenderContext,
|
|
|
|
ComponentPublicInstanceConstructor
|
|
|
|
} from './componentPublicInstance'
|
2020-06-09 15:27:40 +00:00
|
|
|
import {
|
|
|
|
ComponentPropsOptions,
|
|
|
|
NormalizedPropsOptions,
|
|
|
|
initProps
|
|
|
|
} from './componentProps'
|
2020-04-07 01:06:48 +00:00
|
|
|
import { Slots, initSlots, InternalSlots } from './componentSlots'
|
2019-08-30 19:05:39 +00:00
|
|
|
import { warn } from './warning'
|
2020-04-03 23:08:17 +00:00
|
|
|
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
|
2019-12-22 16:27:40 +00:00
|
|
|
import { AppContext, createAppContext, AppConfig } from './apiCreateApp'
|
2020-08-26 22:09:54 +00:00
|
|
|
import { Directive, validateDirectiveName } from './directives'
|
2020-04-03 23:08:17 +00:00
|
|
|
import { applyOptions, ComponentOptions } from './componentOptions'
|
|
|
|
import {
|
|
|
|
EmitsOptions,
|
|
|
|
ObjectEmitsOptions,
|
|
|
|
EmitFn,
|
|
|
|
emit
|
|
|
|
} from './componentEmits'
|
2019-09-06 15:19:22 +00:00
|
|
|
import {
|
|
|
|
EMPTY_OBJ,
|
|
|
|
isFunction,
|
|
|
|
NOOP,
|
2019-10-14 19:36:30 +00:00
|
|
|
isObject,
|
2019-10-16 02:18:55 +00:00
|
|
|
NO,
|
2019-10-17 19:47:26 +00:00
|
|
|
makeMap,
|
2020-01-20 16:24:08 +00:00
|
|
|
isPromise,
|
2020-02-14 06:36:42 +00:00
|
|
|
ShapeFlags
|
2019-09-06 15:19:22 +00:00
|
|
|
} from '@vue/shared'
|
2019-11-04 23:38:55 +00:00
|
|
|
import { SuspenseBoundary } from './components/Suspense'
|
2019-12-11 15:25:34 +00:00
|
|
|
import { CompilerOptions } from '@vue/compiler-core'
|
2020-01-16 22:45:08 +00:00
|
|
|
import {
|
|
|
|
currentRenderingInstance,
|
|
|
|
markAttrsAccessed
|
|
|
|
} from './componentRenderUtils'
|
2020-04-02 01:36:50 +00:00
|
|
|
import { startMeasure, endMeasure } from './profiling'
|
2020-07-21 01:51:30 +00:00
|
|
|
import { devtoolsComponentAdded } from './devtools'
|
2019-05-28 05:27:31 +00:00
|
|
|
|
2020-07-19 02:56:28 +00:00
|
|
|
export type Data = Record<string, unknown>
|
2019-05-29 02:43:27 +00:00
|
|
|
|
2020-07-19 18:09:37 +00:00
|
|
|
/**
|
|
|
|
* For extending allowed non-declared props on components in TSX
|
|
|
|
*/
|
|
|
|
export interface ComponentCustomProps {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default allowed non-declared props on ocmponent in TSX
|
|
|
|
*/
|
|
|
|
export interface AllowedComponentProps {
|
|
|
|
class?: unknown
|
|
|
|
style?: unknown
|
|
|
|
}
|
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
// Note: can't mark this whole interface internal because some public interfaces
|
|
|
|
// extend it.
|
2020-06-09 15:27:40 +00:00
|
|
|
export interface ComponentInternalOptions {
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
__props?: NormalizedPropsOptions | []
|
2020-07-13 15:55:46 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
__emits?: ObjectEmitsOptions
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-12-16 15:36:48 +00:00
|
|
|
__scopeId?: string
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-12-18 02:28:24 +00:00
|
|
|
__cssModules?: Data
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-12-16 15:36:48 +00:00
|
|
|
__hmrId?: string
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* This one should be exposed so that devtools can make use of it
|
|
|
|
*/
|
2020-04-20 20:06:51 +00:00
|
|
|
__file?: string
|
2019-12-16 15:36:48 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 02:12:25 +00:00
|
|
|
export interface FunctionalComponent<P = {}, E extends EmitsOptions = {}>
|
|
|
|
extends ComponentInternalOptions {
|
2020-05-01 14:37:40 +00:00
|
|
|
// use of any here is intentional so it can be a valid JSX Element constructor
|
2020-04-03 16:05:52 +00:00
|
|
|
(props: P, ctx: SetupContext<E>): any
|
2019-05-28 10:06:00 +00:00
|
|
|
props?: ComponentPropsOptions<P>
|
2020-04-03 16:05:52 +00:00
|
|
|
emits?: E | (keyof E)[]
|
2019-10-25 16:12:17 +00:00
|
|
|
inheritAttrs?: boolean
|
2019-05-28 10:06:00 +00:00
|
|
|
displayName?: string
|
|
|
|
}
|
|
|
|
|
2020-03-12 15:46:32 +00:00
|
|
|
export interface ClassComponent {
|
|
|
|
new (...args: any[]): ComponentPublicInstance<any, any, any, any, any>
|
|
|
|
__vccOpts: ComponentOptions
|
|
|
|
}
|
|
|
|
|
2020-08-19 20:11:29 +00:00
|
|
|
/**
|
|
|
|
* Concrete component type matches its actual value: it's either an options
|
|
|
|
* object, or a function. Use this where the code expects to work with actual
|
|
|
|
* values, e.g. checking if its a function or not. This is mostly for internal
|
|
|
|
* implementation code.
|
|
|
|
*/
|
|
|
|
export type ConcreteComponent = ComponentOptions | FunctionalComponent<any, any>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A type used in public APIs where a component type is expected.
|
|
|
|
* The constructor type is an artificial type returned by defineComponent().
|
|
|
|
*/
|
|
|
|
export type Component = ConcreteComponent | ComponentPublicInstanceConstructor
|
2020-02-16 02:04:29 +00:00
|
|
|
|
2019-10-30 02:28:38 +00:00
|
|
|
export { ComponentOptions }
|
2019-09-02 20:09:34 +00:00
|
|
|
|
2019-05-28 11:36:15 +00:00
|
|
|
type LifecycleHook = Function[] | null
|
|
|
|
|
2019-08-30 16:16:09 +00:00
|
|
|
export const enum LifecycleHooks {
|
|
|
|
BEFORE_CREATE = 'bc',
|
|
|
|
CREATED = 'c',
|
|
|
|
BEFORE_MOUNT = 'bm',
|
|
|
|
MOUNTED = 'm',
|
|
|
|
BEFORE_UPDATE = 'bu',
|
|
|
|
UPDATED = 'u',
|
|
|
|
BEFORE_UNMOUNT = 'bum',
|
|
|
|
UNMOUNTED = 'um',
|
|
|
|
DEACTIVATED = 'da',
|
|
|
|
ACTIVATED = 'a',
|
|
|
|
RENDER_TRIGGERED = 'rtg',
|
|
|
|
RENDER_TRACKED = 'rtc',
|
|
|
|
ERROR_CAPTURED = 'ec'
|
2019-05-28 11:36:15 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 13:19:20 +00:00
|
|
|
export interface SetupContext<E = EmitsOptions> {
|
2019-06-19 08:43:34 +00:00
|
|
|
attrs: Data
|
|
|
|
slots: Slots
|
2020-04-03 23:08:17 +00:00
|
|
|
emit: EmitFn<E>
|
2019-06-19 08:43:34 +00:00
|
|
|
}
|
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
export type InternalRenderFunction = {
|
2020-03-23 15:08:22 +00:00
|
|
|
(
|
|
|
|
ctx: ComponentPublicInstance,
|
2020-07-11 02:12:25 +00:00
|
|
|
cache: ComponentInternalInstance['renderCache'],
|
|
|
|
// for compiler-optimized bindings
|
|
|
|
$props: ComponentInternalInstance['props'],
|
|
|
|
$setup: ComponentInternalInstance['setupState'],
|
|
|
|
$data: ComponentInternalInstance['data'],
|
|
|
|
$options: ComponentInternalInstance['ctx']
|
2020-03-23 15:08:22 +00:00
|
|
|
): VNodeChild
|
2020-03-11 20:39:26 +00:00
|
|
|
_rc?: boolean // isRuntimeCompiled
|
2019-12-10 16:14:29 +00:00
|
|
|
}
|
2019-09-05 22:48:49 +00:00
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* We expose a subset of properties on the internal instance as they are
|
|
|
|
* useful for advanced external libraries and tools.
|
|
|
|
*/
|
2019-09-06 16:58:31 +00:00
|
|
|
export interface ComponentInternalInstance {
|
2020-04-02 01:36:50 +00:00
|
|
|
uid: number
|
2020-08-19 20:11:29 +00:00
|
|
|
type: ConcreteComponent
|
2019-09-06 16:58:31 +00:00
|
|
|
parent: ComponentInternalInstance | null
|
|
|
|
root: ComponentInternalInstance
|
2020-05-01 14:37:40 +00:00
|
|
|
appContext: AppContext
|
|
|
|
/**
|
|
|
|
* Vnode representing this component in its parent's vdom tree
|
|
|
|
*/
|
2019-05-29 02:43:27 +00:00
|
|
|
vnode: VNode
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* The pending new vnode from parent updates
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-05-28 09:19:47 +00:00
|
|
|
next: VNode | null
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* Root vnode of this component's own vdom tree
|
|
|
|
*/
|
2019-05-29 02:43:27 +00:00
|
|
|
subTree: VNode
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* The reactive effect for rendering and patching the component. Callable.
|
|
|
|
*/
|
2019-05-28 09:19:47 +00:00
|
|
|
update: ReactiveEffect
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* The render function that returns vdom tree.
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
render: InternalRenderFunction | null
|
|
|
|
/**
|
|
|
|
* Object containing values this component provides for its descendents
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-06-19 14:48:22 +00:00
|
|
|
provides: Data
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2019-10-20 21:00:11 +00:00
|
|
|
accessCache: Data | null
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* cache for render function values that rely on _ctx but won't need updates
|
|
|
|
* after initialized (e.g. inline handlers)
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-02-18 19:43:04 +00:00
|
|
|
renderCache: (Function | VNode)[]
|
2019-06-19 08:43:34 +00:00
|
|
|
|
2020-08-26 22:09:54 +00:00
|
|
|
/**
|
|
|
|
* Resolved component registry, only for components with mixins or extends
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
components: Record<string, ConcreteComponent> | null
|
|
|
|
/**
|
|
|
|
* Resolved directive registry, only for components with mixins or extends
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
directives: Record<string, Directive> | null
|
|
|
|
|
2020-04-16 16:49:50 +00:00
|
|
|
// the rest are only for stateful components ---------------------------------
|
|
|
|
|
2020-08-18 15:12:26 +00:00
|
|
|
/**
|
|
|
|
* main proxy that serves as the public instance (`this`)
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-04-16 16:49:50 +00:00
|
|
|
proxy: ComponentPublicInstance | null
|
2020-05-01 14:37:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* alternative proxy used only for runtime-compiled render functions using
|
|
|
|
* `with` block
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-04-16 16:49:50 +00:00
|
|
|
withProxy: ComponentPublicInstance | null
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2020-04-16 16:49:50 +00:00
|
|
|
ctx: Data
|
|
|
|
|
|
|
|
// internal state
|
2019-09-06 00:36:35 +00:00
|
|
|
data: Data
|
|
|
|
props: Data
|
|
|
|
attrs: Data
|
2020-04-07 01:06:48 +00:00
|
|
|
slots: InternalSlots
|
2020-04-16 15:50:33 +00:00
|
|
|
refs: Data
|
|
|
|
emit: EmitFn
|
2020-07-14 15:48:05 +00:00
|
|
|
// used for keeping track of .once event handlers on components
|
|
|
|
emitted: Record<string, boolean> | null
|
2020-04-16 15:50:33 +00:00
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* setup related
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-04-16 15:50:33 +00:00
|
|
|
setupState: Data
|
2020-08-22 14:40:04 +00:00
|
|
|
/**
|
|
|
|
* devtools access to additional info
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
devtoolsRawSetupState?: any
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-04-16 15:50:33 +00:00
|
|
|
setupContext: SetupContext | null
|
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* suspense related
|
|
|
|
* @internal
|
|
|
|
*/
|
2020-03-30 15:49:51 +00:00
|
|
|
suspense: SuspenseBoundary | null
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-10-30 02:28:38 +00:00
|
|
|
asyncDep: Promise<any> | null
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-10-30 02:28:38 +00:00
|
|
|
asyncResolved: boolean
|
|
|
|
|
2019-08-30 16:16:09 +00:00
|
|
|
// lifecycle
|
2019-11-23 04:32:53 +00:00
|
|
|
isMounted: boolean
|
2019-09-11 13:07:29 +00:00
|
|
|
isUnmounted: boolean
|
2019-10-30 02:28:38 +00:00
|
|
|
isDeactivated: boolean
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.BEFORE_CREATE]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.CREATED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.BEFORE_MOUNT]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.MOUNTED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.BEFORE_UPDATE]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.UPDATED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.BEFORE_UNMOUNT]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.UNMOUNTED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.RENDER_TRACKED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.RENDER_TRIGGERED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.ACTIVATED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.DEACTIVATED]: LifecycleHook
|
2020-05-01 14:37:40 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2019-08-30 16:16:09 +00:00
|
|
|
[LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
|
2019-09-06 00:36:35 +00:00
|
|
|
}
|
2019-05-28 11:36:15 +00:00
|
|
|
|
2019-09-02 20:09:34 +00:00
|
|
|
const emptyAppContext = createAppContext()
|
|
|
|
|
2020-04-02 01:36:50 +00:00
|
|
|
let uid = 0
|
|
|
|
|
2020-01-24 02:01:56 +00:00
|
|
|
export function createComponentInstance(
|
2019-08-28 16:13:36 +00:00
|
|
|
vnode: VNode,
|
2020-03-30 15:49:51 +00:00
|
|
|
parent: ComponentInternalInstance | null,
|
|
|
|
suspense: SuspenseBoundary | null
|
2019-10-09 16:17:42 +00:00
|
|
|
) {
|
2020-08-19 20:11:29 +00:00
|
|
|
const type = vnode.type as ConcreteComponent
|
2019-09-03 22:11:04 +00:00
|
|
|
// inherit parent app context - or - if root, adopt from root vnode
|
|
|
|
const appContext =
|
|
|
|
(parent ? parent.appContext : vnode.appContext) || emptyAppContext
|
2020-07-23 18:33:15 +00:00
|
|
|
|
2019-10-09 16:17:42 +00:00
|
|
|
const instance: ComponentInternalInstance = {
|
2020-04-02 01:36:50 +00:00
|
|
|
uid: uid++,
|
2019-08-28 16:13:36 +00:00
|
|
|
vnode,
|
2020-07-23 18:33:15 +00:00
|
|
|
type,
|
2019-06-03 01:43:28 +00:00
|
|
|
parent,
|
2019-09-03 22:11:04 +00:00
|
|
|
appContext,
|
2020-04-05 22:39:22 +00:00
|
|
|
root: null!, // to be immediately set
|
2019-05-28 11:36:15 +00:00
|
|
|
next: null,
|
2019-10-09 16:17:42 +00:00
|
|
|
subTree: null!, // will be set synchronously right after creation
|
|
|
|
update: null!, // will be set synchronously right after creation
|
2019-06-12 07:43:19 +00:00
|
|
|
render: null,
|
2019-12-10 16:14:29 +00:00
|
|
|
proxy: null,
|
|
|
|
withProxy: null,
|
2019-08-30 16:16:09 +00:00
|
|
|
effects: null,
|
2019-09-03 22:11:04 +00:00
|
|
|
provides: parent ? parent.provides : Object.create(appContext.provides),
|
2019-10-17 02:13:52 +00:00
|
|
|
accessCache: null!,
|
2020-02-18 19:43:04 +00:00
|
|
|
renderCache: [],
|
2019-05-28 11:36:15 +00:00
|
|
|
|
2020-08-26 22:09:54 +00:00
|
|
|
// local resovled assets
|
|
|
|
components: null,
|
|
|
|
directives: null,
|
|
|
|
|
2020-04-16 15:50:33 +00:00
|
|
|
// state
|
2020-04-16 16:49:50 +00:00
|
|
|
ctx: EMPTY_OBJ,
|
2019-08-30 16:16:09 +00:00
|
|
|
data: EMPTY_OBJ,
|
|
|
|
props: EMPTY_OBJ,
|
|
|
|
attrs: EMPTY_OBJ,
|
|
|
|
slots: EMPTY_OBJ,
|
|
|
|
refs: EMPTY_OBJ,
|
2020-04-16 15:50:33 +00:00
|
|
|
setupState: EMPTY_OBJ,
|
|
|
|
setupContext: null,
|
2019-08-30 16:16:09 +00:00
|
|
|
|
2020-03-30 15:49:51 +00:00
|
|
|
// suspense related
|
|
|
|
suspense,
|
2019-09-09 20:00:50 +00:00
|
|
|
asyncDep: null,
|
|
|
|
asyncResolved: false,
|
|
|
|
|
2019-08-30 16:16:09 +00:00
|
|
|
// lifecycle hooks
|
|
|
|
// not using enums here because it results in computed properties
|
2019-11-23 04:32:53 +00:00
|
|
|
isMounted: false,
|
2019-09-11 13:07:29 +00:00
|
|
|
isUnmounted: false,
|
2019-10-30 02:28:38 +00:00
|
|
|
isDeactivated: false,
|
2019-08-30 16:16:09 +00:00
|
|
|
bc: null,
|
|
|
|
c: null,
|
2019-05-28 11:36:15 +00:00
|
|
|
bm: null,
|
|
|
|
m: null,
|
|
|
|
bu: null,
|
|
|
|
u: null,
|
|
|
|
um: null,
|
|
|
|
bum: null,
|
|
|
|
da: null,
|
|
|
|
a: null,
|
|
|
|
rtg: null,
|
|
|
|
rtc: null,
|
|
|
|
ec: null,
|
2020-07-14 15:48:05 +00:00
|
|
|
emit: null as any, // to be set immediately
|
|
|
|
emitted: null
|
2019-05-28 11:36:15 +00:00
|
|
|
}
|
2020-04-05 22:39:22 +00:00
|
|
|
if (__DEV__) {
|
2020-04-16 16:49:50 +00:00
|
|
|
instance.ctx = createRenderContext(instance)
|
2020-04-05 22:39:22 +00:00
|
|
|
} else {
|
2020-04-16 16:49:50 +00:00
|
|
|
instance.ctx = { _: instance }
|
2020-04-05 22:39:22 +00:00
|
|
|
}
|
2019-06-03 01:43:28 +00:00
|
|
|
instance.root = parent ? parent.root : instance
|
2020-04-03 23:08:17 +00:00
|
|
|
instance.emit = emit.bind(null, instance)
|
2020-07-16 22:18:52 +00:00
|
|
|
|
2020-07-21 01:51:30 +00:00
|
|
|
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
|
|
|
devtoolsComponentAdded(instance)
|
|
|
|
}
|
2020-07-16 22:18:52 +00:00
|
|
|
|
2019-06-03 01:43:28 +00:00
|
|
|
return instance
|
2019-05-28 11:36:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 16:58:31 +00:00
|
|
|
export let currentInstance: ComponentInternalInstance | null = null
|
2019-05-28 11:36:15 +00:00
|
|
|
|
2019-09-06 16:58:31 +00:00
|
|
|
export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
|
2019-11-23 04:32:53 +00:00
|
|
|
currentInstance || currentRenderingInstance
|
2019-06-20 07:25:10 +00:00
|
|
|
|
2019-09-06 16:58:31 +00:00
|
|
|
export const setCurrentInstance = (
|
|
|
|
instance: ComponentInternalInstance | null
|
|
|
|
) => {
|
2019-08-30 16:16:09 +00:00
|
|
|
currentInstance = instance
|
|
|
|
}
|
|
|
|
|
2019-10-16 02:18:55 +00:00
|
|
|
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
2019-10-14 19:36:30 +00:00
|
|
|
|
|
|
|
export function validateComponentName(name: string, config: AppConfig) {
|
|
|
|
const appIsNativeTag = config.isNativeTag || NO
|
|
|
|
if (isBuiltInTag(name) || appIsNativeTag(name)) {
|
|
|
|
warn(
|
|
|
|
'Do not use built-in or reserved HTML elements as component id: ' + name
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-29 14:49:17 +00:00
|
|
|
export let isInSSRComponentSetup = false
|
|
|
|
|
2020-01-24 03:23:10 +00:00
|
|
|
export function setupComponent(
|
2019-09-11 14:09:00 +00:00
|
|
|
instance: ComponentInternalInstance,
|
2020-01-29 14:49:17 +00:00
|
|
|
isSSR = false
|
2019-09-11 14:09:00 +00:00
|
|
|
) {
|
2020-01-29 14:49:17 +00:00
|
|
|
isInSSRComponentSetup = isSSR
|
2020-04-06 21:37:47 +00:00
|
|
|
|
2020-01-24 03:23:10 +00:00
|
|
|
const { props, children, shapeFlag } = instance.vnode
|
2020-04-06 21:37:47 +00:00
|
|
|
const isStateful = shapeFlag & ShapeFlags.STATEFUL_COMPONENT
|
|
|
|
initProps(instance, props, isStateful, isSSR)
|
2020-04-07 01:06:48 +00:00
|
|
|
initSlots(instance, children)
|
2020-01-24 03:23:10 +00:00
|
|
|
|
2020-04-06 21:37:47 +00:00
|
|
|
const setupResult = isStateful
|
|
|
|
? setupStatefulComponent(instance, isSSR)
|
|
|
|
: undefined
|
2020-01-29 14:49:17 +00:00
|
|
|
isInSSRComponentSetup = false
|
|
|
|
return setupResult
|
2020-01-24 03:23:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function setupStatefulComponent(
|
|
|
|
instance: ComponentInternalInstance,
|
2020-03-06 19:52:15 +00:00
|
|
|
isSSR: boolean
|
2020-01-24 03:23:10 +00:00
|
|
|
) {
|
2019-05-29 02:43:27 +00:00
|
|
|
const Component = instance.type as ComponentOptions
|
2019-10-14 19:36:30 +00:00
|
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
if (Component.name) {
|
|
|
|
validateComponentName(Component.name, instance.appContext.config)
|
|
|
|
}
|
|
|
|
if (Component.components) {
|
|
|
|
const names = Object.keys(Component.components)
|
|
|
|
for (let i = 0; i < names.length; i++) {
|
2019-10-28 14:13:26 +00:00
|
|
|
validateComponentName(names[i], instance.appContext.config)
|
2019-10-14 19:36:30 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-18 16:34:45 +00:00
|
|
|
if (Component.directives) {
|
|
|
|
const names = Object.keys(Component.directives)
|
|
|
|
for (let i = 0; i < names.length; i++) {
|
|
|
|
validateDirectiveName(names[i])
|
|
|
|
}
|
|
|
|
}
|
2019-10-14 19:36:30 +00:00
|
|
|
}
|
2019-10-17 02:13:52 +00:00
|
|
|
// 0. create render proxy property access cache
|
2019-10-18 02:29:51 +00:00
|
|
|
instance.accessCache = {}
|
2019-12-10 16:14:29 +00:00
|
|
|
// 1. create public instance / render proxy
|
2020-05-01 17:24:38 +00:00
|
|
|
// also mark it raw so it's never observed
|
2020-05-02 20:16:51 +00:00
|
|
|
instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
|
2020-04-05 22:39:22 +00:00
|
|
|
if (__DEV__) {
|
2020-04-16 16:49:50 +00:00
|
|
|
exposePropsOnRenderContext(instance)
|
2020-04-05 22:39:22 +00:00
|
|
|
}
|
2020-04-06 21:37:47 +00:00
|
|
|
// 2. call setup()
|
2019-05-30 15:16:15 +00:00
|
|
|
const { setup } = Component
|
|
|
|
if (setup) {
|
2019-06-19 08:43:34 +00:00
|
|
|
const setupContext = (instance.setupContext =
|
|
|
|
setup.length > 1 ? createSetupContext(instance) : null)
|
2019-09-09 20:00:50 +00:00
|
|
|
|
|
|
|
currentInstance = instance
|
2020-02-18 04:14:07 +00:00
|
|
|
pauseTracking()
|
2020-01-24 16:39:52 +00:00
|
|
|
const setupResult = callWithErrorHandling(
|
2019-08-30 19:05:39 +00:00
|
|
|
setup,
|
|
|
|
instance,
|
2019-09-06 16:58:31 +00:00
|
|
|
ErrorCodes.SETUP_FUNCTION,
|
2020-04-15 03:49:46 +00:00
|
|
|
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
|
2019-08-30 19:05:39 +00:00
|
|
|
)
|
2020-02-18 04:14:07 +00:00
|
|
|
resetTracking()
|
2019-09-09 20:00:50 +00:00
|
|
|
currentInstance = null
|
2019-06-19 14:48:22 +00:00
|
|
|
|
2019-10-17 19:47:26 +00:00
|
|
|
if (isPromise(setupResult)) {
|
2020-03-10 19:28:13 +00:00
|
|
|
if (isSSR) {
|
2020-01-24 16:39:52 +00:00
|
|
|
// return the promise so server-renderer can wait on it
|
2020-03-13 02:19:41 +00:00
|
|
|
return setupResult.then((resolvedResult: unknown) => {
|
2020-04-05 22:39:22 +00:00
|
|
|
handleSetupResult(instance, resolvedResult, isSSR)
|
2020-01-26 21:13:12 +00:00
|
|
|
})
|
2020-01-24 16:39:52 +00:00
|
|
|
} else if (__FEATURE_SUSPENSE__) {
|
2019-09-09 20:28:32 +00:00
|
|
|
// async setup returned Promise.
|
|
|
|
// bail here and wait for re-entry.
|
2019-10-05 14:09:34 +00:00
|
|
|
instance.asyncDep = setupResult
|
2019-09-09 20:28:32 +00:00
|
|
|
} else if (__DEV__) {
|
|
|
|
warn(
|
|
|
|
`setup() returned a Promise, but the version of Vue you are using ` +
|
|
|
|
`does not support it yet.`
|
|
|
|
)
|
|
|
|
}
|
2019-06-12 07:43:19 +00:00
|
|
|
} else {
|
2020-04-05 22:39:22 +00:00
|
|
|
handleSetupResult(instance, setupResult, isSSR)
|
2019-06-12 07:43:19 +00:00
|
|
|
}
|
2019-08-21 21:05:14 +00:00
|
|
|
} else {
|
2020-04-02 01:36:50 +00:00
|
|
|
finishComponentSetup(instance, isSSR)
|
2019-09-09 20:00:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function handleSetupResult(
|
|
|
|
instance: ComponentInternalInstance,
|
2019-09-11 14:09:00 +00:00
|
|
|
setupResult: unknown,
|
2020-03-06 19:52:15 +00:00
|
|
|
isSSR: boolean
|
2019-09-09 20:00:50 +00:00
|
|
|
) {
|
|
|
|
if (isFunction(setupResult)) {
|
|
|
|
// setup returned an inline render function
|
2020-05-01 14:37:40 +00:00
|
|
|
instance.render = setupResult as InternalRenderFunction
|
2019-09-09 20:00:50 +00:00
|
|
|
} else if (isObject(setupResult)) {
|
2019-09-12 03:44:37 +00:00
|
|
|
if (__DEV__ && isVNode(setupResult)) {
|
|
|
|
warn(
|
|
|
|
`setup() should not return VNodes directly - ` +
|
|
|
|
`return a render function instead.`
|
|
|
|
)
|
|
|
|
}
|
2019-09-09 20:00:50 +00:00
|
|
|
// setup returned bindings.
|
|
|
|
// assuming a render function compiled from template is present.
|
2020-08-22 14:40:04 +00:00
|
|
|
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
|
|
|
instance.devtoolsRawSetupState = setupResult
|
|
|
|
}
|
2020-07-28 20:30:56 +00:00
|
|
|
instance.setupState = proxyRefs(setupResult)
|
2020-04-05 22:39:22 +00:00
|
|
|
if (__DEV__) {
|
2020-04-16 16:49:50 +00:00
|
|
|
exposeSetupStateOnRenderContext(instance)
|
2020-04-05 22:39:22 +00:00
|
|
|
}
|
2019-09-09 20:00:50 +00:00
|
|
|
} else if (__DEV__ && setupResult !== undefined) {
|
|
|
|
warn(
|
|
|
|
`setup() should return an object. Received: ${
|
|
|
|
setupResult === null ? 'null' : typeof setupResult
|
|
|
|
}`
|
|
|
|
)
|
|
|
|
}
|
2020-04-02 01:36:50 +00:00
|
|
|
finishComponentSetup(instance, isSSR)
|
2019-09-09 20:00:50 +00:00
|
|
|
}
|
|
|
|
|
2019-09-20 16:16:19 +00:00
|
|
|
type CompileFunction = (
|
2019-12-11 15:25:34 +00:00
|
|
|
template: string | object,
|
2019-09-20 16:16:19 +00:00
|
|
|
options?: CompilerOptions
|
2020-05-01 14:37:40 +00:00
|
|
|
) => InternalRenderFunction
|
2019-09-20 16:16:19 +00:00
|
|
|
|
|
|
|
let compile: CompileFunction | undefined
|
|
|
|
|
2020-04-30 21:04:35 +00:00
|
|
|
/**
|
|
|
|
* For runtime-dom to register the compiler.
|
|
|
|
* Note the exported method uses any to avoid d.ts relying on the compiler types.
|
|
|
|
*/
|
2019-11-02 02:54:01 +00:00
|
|
|
export function registerRuntimeCompiler(_compile: any) {
|
2019-09-20 04:24:16 +00:00
|
|
|
compile = _compile
|
|
|
|
}
|
|
|
|
|
2019-09-11 14:09:00 +00:00
|
|
|
function finishComponentSetup(
|
|
|
|
instance: ComponentInternalInstance,
|
2020-03-06 19:52:15 +00:00
|
|
|
isSSR: boolean
|
2019-09-11 14:09:00 +00:00
|
|
|
) {
|
2019-09-09 20:00:50 +00:00
|
|
|
const Component = instance.type as ComponentOptions
|
2020-03-06 19:52:15 +00:00
|
|
|
|
|
|
|
// template / render function normalization
|
|
|
|
if (__NODE_JS__ && isSSR) {
|
|
|
|
if (Component.render) {
|
2020-05-01 14:37:40 +00:00
|
|
|
instance.render = Component.render as InternalRenderFunction
|
2020-03-06 19:52:15 +00:00
|
|
|
}
|
|
|
|
} else if (!instance.render) {
|
2020-07-27 21:44:17 +00:00
|
|
|
// could be set from setup()
|
2020-03-11 20:39:26 +00:00
|
|
|
if (compile && Component.template && !Component.render) {
|
2020-04-02 01:36:50 +00:00
|
|
|
if (__DEV__) {
|
|
|
|
startMeasure(instance, `compile`)
|
|
|
|
}
|
2020-03-11 20:39:26 +00:00
|
|
|
Component.render = compile(Component.template, {
|
2020-07-23 18:53:09 +00:00
|
|
|
isCustomElement: instance.appContext.config.isCustomElement,
|
|
|
|
delimiters: Component.delimiters
|
2019-10-15 21:50:38 +00:00
|
|
|
})
|
2020-04-03 13:19:53 +00:00
|
|
|
if (__DEV__) {
|
2020-04-02 01:36:50 +00:00
|
|
|
endMeasure(instance, `compile`)
|
|
|
|
}
|
2019-10-15 21:50:38 +00:00
|
|
|
}
|
2019-12-10 16:14:29 +00:00
|
|
|
|
2020-05-01 14:37:40 +00:00
|
|
|
instance.render = (Component.render || NOOP) as InternalRenderFunction
|
2019-12-10 16:14:29 +00:00
|
|
|
|
|
|
|
// for runtime-compiled render functions using `with` blocks, the render
|
|
|
|
// proxy used needs a different `has` handler which is more performant and
|
|
|
|
// also only allows a whitelist of globals to fallthrough.
|
2020-03-11 20:39:26 +00:00
|
|
|
if (instance.render._rc) {
|
2019-12-10 16:14:29 +00:00
|
|
|
instance.withProxy = new Proxy(
|
2020-04-16 16:49:50 +00:00
|
|
|
instance.ctx,
|
2020-04-05 22:39:22 +00:00
|
|
|
RuntimeCompiledPublicInstanceProxyHandlers
|
2019-12-10 16:14:29 +00:00
|
|
|
)
|
|
|
|
}
|
2019-05-28 11:36:15 +00:00
|
|
|
}
|
2019-09-09 20:00:50 +00:00
|
|
|
|
2019-09-04 02:25:38 +00:00
|
|
|
// support for 2.x options
|
2020-07-21 01:51:30 +00:00
|
|
|
if (__FEATURE_OPTIONS_API__) {
|
2019-09-09 20:00:50 +00:00
|
|
|
currentInstance = instance
|
2019-09-04 15:36:27 +00:00
|
|
|
applyOptions(instance, Component)
|
2019-09-09 20:00:50 +00:00
|
|
|
currentInstance = null
|
2019-09-04 02:25:38 +00:00
|
|
|
}
|
2020-07-27 21:44:17 +00:00
|
|
|
|
|
|
|
// warn missing template/render
|
|
|
|
if (__DEV__ && !Component.render && instance.render === NOOP) {
|
|
|
|
/* istanbul ignore if */
|
|
|
|
if (!compile && Component.template) {
|
|
|
|
warn(
|
|
|
|
`Component provided template option but ` +
|
|
|
|
`runtime compilation is not supported in this build of Vue.` +
|
|
|
|
(__ESM_BUNDLER__
|
|
|
|
? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
|
|
|
|
: __ESM_BROWSER__
|
|
|
|
? ` Use "vue.esm-browser.js" instead.`
|
|
|
|
: __GLOBAL__
|
|
|
|
? ` Use "vue.global.js" instead.`
|
|
|
|
: ``) /* should not happen */
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
warn(`Component is missing template or render function.`)
|
|
|
|
}
|
|
|
|
}
|
2019-05-28 11:36:15 +00:00
|
|
|
}
|
2019-05-28 09:19:47 +00:00
|
|
|
|
2020-04-07 01:06:48 +00:00
|
|
|
const attrHandlers: ProxyHandler<Data> = {
|
|
|
|
get: (target, key: string) => {
|
2020-04-20 20:40:59 +00:00
|
|
|
if (__DEV__) {
|
|
|
|
markAttrsAccessed()
|
|
|
|
}
|
2020-04-06 21:57:27 +00:00
|
|
|
return target[key]
|
|
|
|
},
|
2020-04-07 01:06:48 +00:00
|
|
|
set: () => {
|
|
|
|
warn(`setupContext.attrs is readonly.`)
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
deleteProperty: () => {
|
|
|
|
warn(`setupContext.attrs is readonly.`)
|
|
|
|
return false
|
|
|
|
}
|
2020-04-06 21:57:27 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 16:58:31 +00:00
|
|
|
function createSetupContext(instance: ComponentInternalInstance): SetupContext {
|
2020-04-07 01:06:48 +00:00
|
|
|
if (__DEV__) {
|
|
|
|
// We use getters in dev in case libs like test-utils overwrite instance
|
|
|
|
// properties (overwrites should not be done in prod)
|
|
|
|
return Object.freeze({
|
|
|
|
get attrs() {
|
|
|
|
return new Proxy(instance.attrs, attrHandlers)
|
|
|
|
},
|
|
|
|
get slots() {
|
2020-04-15 03:49:46 +00:00
|
|
|
return shallowReadonly(instance.slots)
|
2020-04-07 01:06:48 +00:00
|
|
|
},
|
|
|
|
get emit() {
|
2020-04-13 14:06:41 +00:00
|
|
|
return (event: string, ...args: any[]) => instance.emit(event, ...args)
|
2020-04-07 01:06:48 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
attrs: instance.attrs,
|
|
|
|
slots: instance.slots,
|
|
|
|
emit: instance.emit
|
2020-02-10 02:47:16 +00:00
|
|
|
}
|
2019-10-05 14:09:34 +00:00
|
|
|
}
|
2019-06-19 08:43:34 +00:00
|
|
|
}
|
2020-02-14 05:13:54 +00:00
|
|
|
|
|
|
|
// record effects created during a component's setup() so that they can be
|
|
|
|
// stopped when the component unmounts
|
|
|
|
export function recordInstanceBoundEffect(effect: ReactiveEffect) {
|
|
|
|
if (currentInstance) {
|
|
|
|
;(currentInstance.effects || (currentInstance.effects = [])).push(effect)
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 01:36:50 +00:00
|
|
|
|
|
|
|
const classifyRE = /(?:^|[-_])(\w)/g
|
|
|
|
const classify = (str: string): string =>
|
|
|
|
str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')
|
|
|
|
|
2020-07-15 14:38:45 +00:00
|
|
|
/* istanbul ignore next */
|
2020-04-02 01:36:50 +00:00
|
|
|
export function formatComponentName(
|
2020-06-26 13:28:15 +00:00
|
|
|
instance: ComponentInternalInstance | null,
|
2020-08-19 20:11:29 +00:00
|
|
|
Component: ConcreteComponent,
|
2020-04-20 20:06:51 +00:00
|
|
|
isRoot = false
|
2020-04-02 01:36:50 +00:00
|
|
|
): string {
|
|
|
|
let name = isFunction(Component)
|
|
|
|
? Component.displayName || Component.name
|
|
|
|
: Component.name
|
2020-04-20 20:06:51 +00:00
|
|
|
if (!name && Component.__file) {
|
|
|
|
const match = Component.__file.match(/([^/\\]+)\.vue$/)
|
2020-04-02 01:36:50 +00:00
|
|
|
if (match) {
|
|
|
|
name = match[1]
|
|
|
|
}
|
|
|
|
}
|
2020-06-26 13:28:15 +00:00
|
|
|
|
|
|
|
if (!name && instance && instance.parent) {
|
2020-07-23 18:33:15 +00:00
|
|
|
// try to infer the name based on reverse resolution
|
|
|
|
const inferFromRegistry = (registry: Record<string, any> | undefined) => {
|
|
|
|
for (const key in registry) {
|
|
|
|
if (registry[key] === Component) {
|
|
|
|
return key
|
|
|
|
}
|
2020-06-26 13:28:15 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-23 18:33:15 +00:00
|
|
|
name =
|
|
|
|
inferFromRegistry(
|
2020-08-26 22:09:54 +00:00
|
|
|
instance.components ||
|
|
|
|
(instance.parent.type as ComponentOptions).components
|
2020-07-23 18:33:15 +00:00
|
|
|
) || inferFromRegistry(instance.appContext.components)
|
2020-06-26 13:28:15 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 20:06:51 +00:00
|
|
|
return name ? classify(name) : isRoot ? `App` : `Anonymous`
|
2020-04-02 01:36:50 +00:00
|
|
|
}
|