__NODE_JS__: true,
__FEATURE_OPTIONS_API__: true,
__FEATURE_SUSPENSE__: true,
- __FEATURE_PROD_DEVTOOLS__: false
+ __FEATURE_PROD_DEVTOOLS__: false,
+ __COMPAT__: true
},
coverageDirectory: 'coverage',
coverageReporters: ['html', 'lcov', 'text'],
ConcreteComponent,
Data,
validateComponentName,
- Component,
- createComponentInstance,
- setupComponent,
- finishComponentSetup
+ Component
} from './component'
import { ComponentOptions } from './componentOptions'
import { ComponentPublicInstance } from './componentPublicInstance'
import { createVNode, cloneVNode, VNode } from './vnode'
import { RootHydrateFunction } from './hydration'
import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
+import { isFunction, NO, isObject } from '@vue/shared'
import { version } from '.'
-import {
- isFunction,
- NO,
- isObject,
- warnDeprecation,
- DeprecationTypes
-} from '@vue/shared'
+import { installCompatMount } from './compat/globalMount'
+import { installLegacyConfigTraps } from './compat/globalConfig'
export interface App<HostElement = any> {
version: string
})
if (__COMPAT__) {
- /**
- * Vue 2 supports the behavior of creating a component instance but not
- * mounting it, which is no longer possible in Vue 3 - this internal
- * function simulates that behavior.
- */
- app._createRoot = options => {
- const vnode = createVNode(
- rootComponent as ConcreteComponent,
- options.propsData || null
- )
- vnode.appContext = context
-
- const hasNoRender =
- !isFunction(rootComponent) &&
- !rootComponent.render &&
- !rootComponent.template
- const emptyRender = () => {}
-
- // create root instance
- const instance = createComponentInstance(vnode, null, null)
- // suppress "missing render fn" warning since it can't be determined
- // until $mount is called
- if (hasNoRender) {
- instance.render = emptyRender
- }
- setupComponent(instance, __NODE_JS__)
- vnode.component = instance
-
- // $mount & $destroy
- // these are defined on ctx and picked up by the $mount/$destroy
- // public property getters on the instance proxy.
- // Note: the following assumes DOM environment since the compat build
- // only targets web. It essentially includes logic for app.mount from
- // both runtime-core AND runtime-dom.
- instance.ctx._compat_mount = (selectorOrEl: string | Element) => {
- if (isMounted) {
- __DEV__ && warn(`Root instance is already mounted.`)
- return
- }
-
- let container: Element
- if (typeof selectorOrEl === 'string') {
- // eslint-disable-next-line
- const result = document.querySelector(selectorOrEl)
- if (!result) {
- __DEV__ &&
- warn(
- `Failed to mount root instance: selector "${selectorOrEl}" returned null.`
- )
- return
- }
- container = result
- } else {
- if (!selectorOrEl) {
- __DEV__ &&
- warn(
- `Failed to mount root instance: invalid mount target ${selectorOrEl}.`
- )
- return
- }
- container = selectorOrEl
- }
-
- const isSVG = container instanceof SVGElement
-
- // HMR root reload
- if (__DEV__) {
- context.reload = () => {
- const cloned = cloneVNode(vnode)
- // compat mode will use instance if not reset to null
- cloned.component = null
- render(cloned, container, isSVG)
- }
- }
-
- // resolve in-DOM template if component did not provide render
- // and no setup/mixin render functions are provided (by checking
- // that the instance is still using the placeholder render fn)
- if (hasNoRender && instance.render === emptyRender) {
- // root directives check
- if (__DEV__) {
- for (let i = 0; i < container.attributes.length; i++) {
- const attr = container.attributes[i]
- if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
- warnDeprecation(DeprecationTypes.DOM_TEMPLATE_MOUNT)
- break
- }
- }
- }
- instance.render = null
- ;(rootComponent as ComponentOptions).template = container.innerHTML
- finishComponentSetup(instance, __NODE_JS__, true /* skip options */)
- }
-
- // clear content before mounting
- container.innerHTML = ''
-
- // TODO hydration
- render(vnode, container, isSVG)
-
- if (container instanceof Element) {
- container.removeAttribute('v-cloak')
- container.setAttribute('data-v-app', '')
- }
-
- isMounted = true
- app._container = container
- // for devtools and telemetry
- ;(container as any).__vue_app__ = app
- if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
- devtoolsInitApp(app, version)
- }
-
- return instance.proxy!
- }
-
- instance.ctx._compat_destroy = app.unmount
-
- return instance.proxy!
- }
+ installCompatMount(app, context, render, hydrate)
+ installLegacyConfigTraps(app.config)
}
return app
--- /dev/null
+import { isRuntimeOnly } from '../component'
+
+export const enum DeprecationTypes {
+ DOM_TEMPLATE_MOUNT,
+ $MOUNT,
+ $DESTROY,
+
+ CONFIG_SILENT,
+ CONFIG_DEVTOOLS,
+ CONFIG_KEY_CODES,
+ CONFIG_PRODUCTION_TIP,
+ CONFIG_IGNORED_ELEMENTS
+}
+
+type DeprecationData = {
+ message: string | (() => string)
+ link?: string
+}
+
+const deprecations: Record<DeprecationTypes, DeprecationData> = {
+ [DeprecationTypes.DOM_TEMPLATE_MOUNT]: {
+ message:
+ `Vue detected directives on the mount container. ` +
+ `In Vue 3, the container is no longer considered part of the template ` +
+ `and will not be processed/replaced.`,
+ link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
+ },
+
+ [DeprecationTypes.$MOUNT]: {
+ message:
+ `vm.$mount() has been removed. ` +
+ `Use createApp(RootComponent).mount() instead.`,
+ link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
+ },
+
+ [DeprecationTypes.$DESTROY]: {
+ message: `vm.$destroy() has been removed. Use app.unmount() instead.`,
+ link: `https://v3.vuejs.org/api/application-api.html#unmount`
+ },
+
+ [DeprecationTypes.CONFIG_SILENT]: {
+ message:
+ `config.silent has been removed because it is not good practice to ` +
+ `intentionally suppress warnings. You can use your browser console's ` +
+ `filter features to focus on relevant messages.`
+ },
+
+ [DeprecationTypes.CONFIG_DEVTOOLS]: {
+ message:
+ `config.devtools has been removed. To enable devtools for ` +
+ `production, configure the __VUE_PROD_DEVTOOLS__ compile-time flag.`,
+ link: `https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags`
+ },
+
+ [DeprecationTypes.CONFIG_KEY_CODES]: {
+ message:
+ `config.keyCodes has been removed. ` +
+ `In Vue 3, you can directly use the kebab-case key names as v-on modifiers.`,
+ link: `https://v3.vuejs.org/guide/migration/keycode-modifiers.html`
+ },
+
+ [DeprecationTypes.CONFIG_PRODUCTION_TIP]: {
+ message: `config.productionTip has been removed.`,
+ link: `https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed`
+ },
+
+ [DeprecationTypes.CONFIG_IGNORED_ELEMENTS]: {
+ message: () => {
+ let msg = `config.ignoredElements has been removed.`
+ if (isRuntimeOnly()) {
+ msg += ` Pass the "isCustomElement" option to @vue/compiler-dom instead.`
+ } else {
+ msg += ` Use config.isCustomElement instead.`
+ }
+ return msg
+ },
+ link: `https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement`
+ }
+}
+
+export function warnDeprecation(key: DeprecationTypes) {
+ if (!__COMPAT__ || !__DEV__) {
+ return
+ }
+ const { message, link } = deprecations[key]
+ console.warn(
+ `[Vue Deprecation]: ${typeof message === 'function' ? message() : message}${
+ link ? `\nFor more details, see ${link}` : ``
+ }`
+ )
+}
--- /dev/null
+import { reactive } from '@vue/reactivity'
+import { extend } from '@vue/shared'
+import { createApp } from '../../../runtime-dom/src'
+import { App, AppConfig, Plugin } from '../apiCreateApp'
+import { defineComponent } from '../apiDefineComponent'
+import { Component, ComponentOptions, isRuntimeOnly } from '../component'
+import { RenderFunction } from '../componentOptions'
+import { ComponentPublicInstance } from '../componentPublicInstance'
+import { Directive } from '../directives'
+import { nextTick } from '../scheduler'
+
+/**
+ * @deprecated the default `Vue` export has been removed in Vue 3. The type for
+ * the default export is provided only for migration purposes. Please use
+ * named imports instead - e.g. `import { createApp } from 'vue'`.
+ */
+export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
+ // no inference here since these types are not meant for actual use - they
+ // are merely here to provide type checks for internal implementation and
+ // information for migration.
+ new (options?: ComponentOptions): ComponentPublicInstance
+
+ version: string
+ config: AppConfig
+
+ extend: typeof defineComponent
+ nextTick: typeof nextTick
+
+ use(plugin: Plugin, ...options: any[]): CompatVue
+ mixin(mixin: ComponentOptions): CompatVue
+
+ component(name: string): Component | undefined
+ component(name: string, component: Component): CompatVue
+ directive(name: string): Directive | undefined
+ directive(name: string, directive: Directive): CompatVue
+
+ compile(template: string): RenderFunction
+
+ /**
+ * @deprecated Vue 3 no longer needs set() for adding new properties.
+ */
+ set(target: any, key: string | number | symbol, value: any): void
+ /**
+ * @deprecated Vue 3 no longer needs delete() for property deletions.
+ */
+ delete(target: any, key: string | number | symbol): void
+ /**
+ * @deprecated use `reactive` instead.
+ */
+ observable: typeof reactive
+ /**
+ * @deprecated filters have been removed from Vue 3.
+ */
+ filter(name: string, arg: any): null
+}
+
+export let isCopyingConfig = false
+
+// Legacy global Vue constructor
+export function createCompatVue(): CompatVue {
+ if (!__COMPAT__) {
+ // @ts-ignore this function will never be called in non-compat mode
+ return
+ }
+
+ const Vue: CompatVue = function Vue(options: ComponentOptions = {}) {
+ return createCompatApp(options, Vue)
+ } as any
+
+ const singletonApp = createApp({})
+
+ function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
+ const app = createApp(options)
+
+ // copy over global config mutations
+ isCopyingConfig = true
+ for (const key in singletonApp.config) {
+ if (
+ key !== 'isNativeTag' &&
+ !(key === 'isCustomElement' && isRuntimeOnly())
+ ) {
+ // @ts-ignore
+ app.config[key] = singletonApp.config[key]
+ }
+ }
+ isCopyingConfig = false
+
+ // copy prototype augmentations as config.globalProperties
+ for (const key in Ctor.prototype) {
+ app.config.globalProperties[key] = Ctor.prototype[key]
+ }
+
+ const vm = app._createRoot!(options)
+ if (options.el) {
+ return (vm as any).$mount(options.el)
+ } else {
+ return vm
+ }
+ }
+
+ Vue.version = __VERSION__
+ Vue.config = singletonApp.config
+
+ Vue.extend = ((options: ComponentOptions = {}) => {
+ function SubVue(inlineOptions?: ComponentOptions) {
+ if (!inlineOptions) {
+ return createCompatApp(options, SubVue)
+ } else {
+ return createCompatApp(
+ {
+ el: inlineOptions.el,
+ extends: options,
+ mixins: [inlineOptions]
+ },
+ SubVue
+ )
+ }
+ }
+ SubVue.prototype = Object.create(Vue.prototype)
+ SubVue.prototype.constructor = SubVue
+ return SubVue
+ }) as any
+
+ Vue.nextTick = nextTick
+
+ Vue.set = (target, key, value) => {
+ // TODO deprecation warnings
+ target[key] = value
+ }
+ Vue.delete = (target, key) => {
+ // TODO deprecation warnings
+ delete target[key]
+ }
+ // TODO wrap with deprecation warning
+ Vue.observable = reactive
+
+ Vue.use = (p, ...options) => {
+ singletonApp.use(p, ...options)
+ return Vue
+ }
+
+ Vue.mixin = m => {
+ singletonApp.mixin(m)
+ return Vue
+ }
+
+ Vue.component = ((name: string, comp: any) => {
+ if (comp) {
+ singletonApp.component(name, comp)
+ return Vue
+ } else {
+ return singletonApp.component(name)
+ }
+ }) as any
+
+ Vue.directive = ((name: string, dir: any) => {
+ if (dir) {
+ singletonApp.directive(name, dir)
+ return Vue
+ } else {
+ return singletonApp.directive(name)
+ }
+ }) as any
+
+ Vue.filter = ((name: string, filter: any) => {
+ // TODO deprecation warning
+ // TODO compiler warning for filters (maybe behavior compat?)
+ }) as any
+
+ return Vue
+}
--- /dev/null
+import { AppConfig } from '../apiCreateApp'
+import { DeprecationTypes, warnDeprecation } from './deprecations'
+import { isCopyingConfig } from './global'
+
+// legacy config warnings
+export type LegacyConfig = {
+ /**
+ * @deprecated `config.silent` option has been removed
+ */
+ silent?: boolean
+ /**
+ * @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead
+ * https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
+ */
+ devtools?: boolean
+ /**
+ * @deprecated use `config.isCustomElement` instead
+ * https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement
+ */
+ ignoredElements?: (string | RegExp)[]
+ /**
+ * @deprecated
+ * https://v3.vuejs.org/guide/migration/keycode-modifiers.html
+ */
+ keyCodes?: Record<string, number | number[]>
+ /**
+ * @deprecated
+ * https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed
+ */
+ productionTip?: boolean
+}
+
+export function installLegacyConfigTraps(config: AppConfig) {
+ const legacyConfigOptions: Record<string, DeprecationTypes> = {
+ silent: DeprecationTypes.CONFIG_SILENT,
+ devtools: DeprecationTypes.CONFIG_DEVTOOLS,
+ ignoredElements: DeprecationTypes.CONFIG_IGNORED_ELEMENTS,
+ keyCodes: DeprecationTypes.CONFIG_KEY_CODES,
+ productionTip: DeprecationTypes.CONFIG_PRODUCTION_TIP
+ }
+
+ Object.keys(legacyConfigOptions).forEach(key => {
+ let val = (config as any)[key]
+ Object.defineProperty(config, key, {
+ enumerable: true,
+ get() {
+ return val
+ },
+ set(newVal) {
+ if (!isCopyingConfig) {
+ warnDeprecation(legacyConfigOptions[key])
+ }
+ val = newVal
+ }
+ })
+ })
+}
--- /dev/null
+import { isFunction } from '@vue/shared'
+import { App, AppContext } from '../apiCreateApp'
+import {
+ ComponentOptions,
+ createComponentInstance,
+ finishComponentSetup,
+ setupComponent
+} from '../component'
+import { devtoolsInitApp } from '../devtools'
+import { RootHydrateFunction } from '../hydration'
+import { RootRenderFunction } from '../renderer'
+import { cloneVNode, createVNode } from '../vnode'
+import { warn } from '../warning'
+import { version } from '..'
+import { DeprecationTypes, warnDeprecation } from './deprecations'
+
+export function installCompatMount(
+ app: App,
+ context: AppContext,
+ render: RootRenderFunction,
+ hydrate?: RootHydrateFunction
+) {
+ let isMounted = false
+
+ /**
+ * Vue 2 supports the behavior of creating a component instance but not
+ * mounting it, which is no longer possible in Vue 3 - this internal
+ * function simulates that behavior.
+ */
+ app._createRoot = options => {
+ const component = app._component
+ const vnode = createVNode(component, options.propsData || null)
+ vnode.appContext = context
+
+ const hasNoRender =
+ !isFunction(component) && !component.render && !component.template
+ const emptyRender = () => {}
+
+ // create root instance
+ const instance = createComponentInstance(vnode, null, null)
+ // suppress "missing render fn" warning since it can't be determined
+ // until $mount is called
+ if (hasNoRender) {
+ instance.render = emptyRender
+ }
+ setupComponent(instance, __NODE_JS__)
+ vnode.component = instance
+
+ // $mount & $destroy
+ // these are defined on ctx and picked up by the $mount/$destroy
+ // public property getters on the instance proxy.
+ // Note: the following assumes DOM environment since the compat build
+ // only targets web. It essentially includes logic for app.mount from
+ // both runtime-core AND runtime-dom.
+ instance.ctx._compat_mount = (selectorOrEl: string | Element) => {
+ if (isMounted) {
+ __DEV__ && warn(`Root instance is already mounted.`)
+ return
+ }
+
+ let container: Element
+ if (typeof selectorOrEl === 'string') {
+ // eslint-disable-next-line
+ const result = document.querySelector(selectorOrEl)
+ if (!result) {
+ __DEV__ &&
+ warn(
+ `Failed to mount root instance: selector "${selectorOrEl}" returned null.`
+ )
+ return
+ }
+ container = result
+ } else {
+ if (!selectorOrEl) {
+ __DEV__ &&
+ warn(
+ `Failed to mount root instance: invalid mount target ${selectorOrEl}.`
+ )
+ return
+ }
+ container = selectorOrEl
+ }
+
+ const isSVG = container instanceof SVGElement
+
+ // HMR root reload
+ if (__DEV__) {
+ context.reload = () => {
+ const cloned = cloneVNode(vnode)
+ // compat mode will use instance if not reset to null
+ cloned.component = null
+ render(cloned, container, isSVG)
+ }
+ }
+
+ // resolve in-DOM template if component did not provide render
+ // and no setup/mixin render functions are provided (by checking
+ // that the instance is still using the placeholder render fn)
+ if (hasNoRender && instance.render === emptyRender) {
+ // root directives check
+ if (__DEV__) {
+ for (let i = 0; i < container.attributes.length; i++) {
+ const attr = container.attributes[i]
+ if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
+ warnDeprecation(DeprecationTypes.DOM_TEMPLATE_MOUNT)
+ break
+ }
+ }
+ }
+ instance.render = null
+ ;(component as ComponentOptions).template = container.innerHTML
+ finishComponentSetup(instance, __NODE_JS__, true /* skip options */)
+ }
+
+ // clear content before mounting
+ container.innerHTML = ''
+
+ // TODO hydration
+ render(vnode, container, isSVG)
+
+ if (container instanceof Element) {
+ container.removeAttribute('v-cloak')
+ container.setAttribute('data-v-app', '')
+ }
+
+ isMounted = true
+ app._container = container
+ // for devtools and telemetry
+ ;(container as any).__vue_app__ = app
+ if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
+ devtoolsInitApp(app, version)
+ }
+
+ return instance.proxy!
+ }
+
+ instance.ctx._compat_destroy = app.unmount
+
+ return instance.proxy!
+ }
+}
NOOP,
extend,
isString,
- warnDeprecation,
- DeprecationTypes
+ isFunction
} from '@vue/shared'
import {
ReactiveEffect,
import { currentRenderingInstance } from './componentRenderContext'
import { warn } from './warning'
import { UnionToIntersection } from './helpers/typeUtils'
-
+import { warnDeprecation, DeprecationTypes } from './compat/deprecations'
/**
* Custom properties added to component instances in any way and can be accessed through `this`
*
((globalProperties = appContext.config.globalProperties),
hasOwn(globalProperties, key))
) {
- return globalProperties[key]
+ if (__COMPAT__) {
+ const val = globalProperties[key]
+ return isFunction(val) ? val.bind(instance.proxy) : val
+ } else {
+ return globalProperties[key]
+ }
} else if (
__DEV__ &&
currentRenderingInstance &&
Object.defineProperty(target, key, {
configurable: true,
enumerable: false,
- get: () => globalProperties[key],
+ get: () => {
+ const val = globalProperties[key]
+ return __COMPAT__ && isFunction(val) ? val.bind(instance.proxy) : val
+ },
set: NOOP
})
})
* @internal
*/
export const ssrUtils = (__NODE_JS__ ? _ssrUtils : null) as typeof _ssrUtils
+
+// 2.x COMPAT ------------------------------------------------------------------
+
+// Important: every function exported here must have `if (!__COMPAT__) return`
+// checks
+export { warnDeprecation, DeprecationTypes } from './compat/deprecations'
+export { createCompatVue, CompatVue } from './compat/global'
HydrationRenderer,
App,
RootHydrateFunction,
- isRuntimeOnly
+ isRuntimeOnly,
+ warnDeprecation,
+ DeprecationTypes
} from '@vue/runtime-core'
import { nodeOps } from './nodeOps'
import { patchProp, forcePatchProp } from './patchProp'
// Importing from the compiler, will be tree-shaken in prod
-import {
- isFunction,
- isString,
- isHTMLTag,
- isSVGTag,
- extend,
- warnDeprecation,
- DeprecationTypes
-} from '@vue/shared'
+import { isFunction, isString, isHTMLTag, isSVGTag, extend } from '@vue/shared'
declare module '@vue/reactivity' {
export interface RefUnwrapBailTypes {
+++ /dev/null
-export const enum DeprecationTypes {
- DOM_TEMPLATE_MOUNT,
- $MOUNT,
- $DESTROY
-}
-
-type DeprecationData = {
- message: string
- link?: string
-}
-
-const deprecations: Record<DeprecationTypes, DeprecationData> = {
- [DeprecationTypes.DOM_TEMPLATE_MOUNT]: {
- message:
- `Vue detected directives on the mount container. ` +
- `In Vue 3, the container is no longer considered part of the template ` +
- `and will not be processed/replaced.`,
- link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
- },
-
- [DeprecationTypes.$MOUNT]: {
- message:
- `vm.$mount() has been deprecated. ` +
- `Use createApp(RootComponent).mount() instead.`,
- link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
- },
-
- [DeprecationTypes.$DESTROY]: {
- message: `vm.$destroy() has been deprecated. Use app.unmount() instead.`,
- link: `https://v3.vuejs.org/api/application-api.html#unmount`
- }
-}
-
-export function warnDeprecation(key: DeprecationTypes) {
- const { message, link } = deprecations[key]
- console.warn(
- `[Deprecation]: ${message}${link ? `\nFor more details, see ${link}` : ``}`
- )
-}
export * from './escapeHtml'
export * from './looseEqual'
export * from './toDisplayString'
-export * from './deprecations'
/**
* List of @babel/parser plugins that are used for template expression
+++ /dev/null
-import { reactive } from '@vue/reactivity'
-import {
- createApp,
- defineComponent,
- nextTick,
- App,
- AppConfig,
- Plugin,
- Component,
- ComponentOptions,
- ComponentPublicInstance,
- Directive,
- RenderFunction,
- isRuntimeOnly
-} from '@vue/runtime-dom'
-import { extend } from '@vue/shared'
-
-// TODO make these getter/setters and trigger deprecation warnings
-export type LegacyConfig = AppConfig & {
- /**
- * @deprecated `config.silent` option has been removed
- */
- silent?: boolean
- /**
- * @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead
- * https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
- */
- devtools?: boolean
- /**
- * @deprecated use `config.isCustomElement` instead
- * https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement
- */
- ignoredElements?: (string | RegExp)[]
- /**
- * @deprecated
- * https://v3.vuejs.org/guide/migration/keycode-modifiers.html
- */
- keyCodes?: Record<string, number | number[]>
- /**
- * @deprecated
- * https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed
- */
- productionTip?: boolean
-}
-
-/**
- * @deprecated the default `Vue` export has been removed in Vue 3. The type for
- * the default export is provided only for migration purposes. Please use
- * named imports instead - e.g. `import { createApp } from 'vue'`.
- */
-export type GlobalVue = Pick<App, 'version' | 'component' | 'directive'> & {
- // no inference here since these types are not meant for actual use - they
- // are merely here to provide type checks for internal implementation and
- // information for migration.
- new (options?: ComponentOptions): ComponentPublicInstance
-
- version: string
- config: LegacyConfig
-
- extend: typeof defineComponent
- nextTick: typeof nextTick
-
- use(plugin: Plugin, ...options: any[]): GlobalVue
- mixin(mixin: ComponentOptions): GlobalVue
-
- component(name: string): Component | undefined
- component(name: string, component: Component): GlobalVue
- directive(name: string): Directive | undefined
- directive(name: string, directive: Directive): GlobalVue
-
- compile(template: string): RenderFunction
-
- /**
- * @deprecated Vue 3 no longer needs set() for adding new properties.
- */
- set(target: any, key: string | number | symbol, value: any): void
- /**
- * @deprecated Vue 3 no longer needs delete() for property deletions.
- */
- delete(target: any, key: string | number | symbol): void
- /**
- * @deprecated use `reactive` instead.
- */
- observable: typeof reactive
- /**
- * @deprecated filters have been removed from Vue 3.
- */
- filter(name: string, arg: any): null
-}
-
-export const Vue: GlobalVue = function Vue(options: ComponentOptions = {}) {
- const app = createApp(options)
-
- // copy over global config mutations
- for (const key in singletonApp.config) {
- if (
- key !== 'isNativeTag' &&
- !(key === 'isCustomElement' && isRuntimeOnly())
- ) {
- // @ts-ignore
- app.config[key] = singletonApp.config[key]
- }
- }
-
- // TODO copy prototype augmentations as config.globalProperties
-
- if (options.el) {
- return app.mount(options.el)
- } else {
- return app._createRoot!(options)
- }
-} as any
-
-const singletonApp = createApp({})
-
-Vue.version = __VERSION__
-Vue.config = singletonApp.config
-
-Vue.extend = ((baseOptions: ComponentOptions = {}) => {
- return function ExtendedVueConstructor(inlineOptions?: ComponentOptions) {
- if (!inlineOptions) {
- return new Vue(baseOptions)
- } else {
- const mergedOptions = extend({}, baseOptions)
- mergedOptions.mixins = [inlineOptions, ...(mergedOptions.mixins || [])]
- return new Vue(mergedOptions)
- }
- }
-}) as any
-
-Vue.nextTick = nextTick
-
-Vue.set = (target, key, value) => {
- // TODO deprecation warnings
- target[key] = value
-}
-Vue.delete = (target, key) => {
- // TODO deprecation warnings
- delete target[key]
-}
-// TODO wrap with deprecation warning
-Vue.observable = reactive
-
-Vue.use = (p, ...options) => {
- singletonApp.use(p, ...options)
- return Vue
-}
-
-Vue.mixin = m => {
- singletonApp.mixin(m)
- return Vue
-}
-
-Vue.component = ((name: string, comp: any) => {
- if (comp) {
- singletonApp.component(name, comp)
- return Vue
- } else {
- return singletonApp.component(name)
- }
-}) as any
-
-Vue.directive = ((name: string, dir: any) => {
- if (dir) {
- singletonApp.directive(name, dir)
- return Vue
- } else {
- return singletonApp.directive(name)
- }
-}) as any
-
-Vue.filter = ((name: string, filter: any) => {
- // TODO deprecation warning
- // TODO compiler warning for filters (maybe behavior compat?)
-}) as any
// and the compiler, and supports on-the-fly compilation of the template option.
import { initDev } from './dev'
import { compile, CompilerOptions, CompilerError } from '@vue/compiler-dom'
-import { registerRuntimeCompiler, RenderFunction, warn } from '@vue/runtime-dom'
+import {
+ registerRuntimeCompiler,
+ RenderFunction,
+ warn,
+ createCompatVue
+} from '@vue/runtime-dom'
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
import { InternalRenderFunction } from 'packages/runtime-core/src/component'
import * as runtimeDom from '@vue/runtime-dom'
-import { Vue } from './apiGlobal'
if (__DEV__) {
initDev()
registerRuntimeCompiler(compileToFunction)
+const Vue = createCompatVue()
+
Vue.compile = compileToFunction
extend(Vue, runtimeDom)