]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: make legacy global apis available on app instance as well
authorEvan You <yyx990803@gmail.com>
Thu, 6 May 2021 21:15:11 +0000 (17:15 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 6 May 2021 21:15:11 +0000 (17:15 -0400)
packages/runtime-core/src/apiCreateApp.ts
packages/runtime-core/src/compat/compatConfig.ts
packages/runtime-core/src/compat/filter.ts [deleted file]
packages/runtime-core/src/compat/global.ts

index b134a482bff7bc4bb90f18b6208b7f9df07d2bfa..a6736b797bff2dacfde43f019c7e1ee91ee25aae 100644 (file)
@@ -15,9 +15,7 @@ import { RootHydrateFunction } from './hydration'
 import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
 import { isFunction, NO, isObject } from '@vue/shared'
 import { version } from '.'
-import { applySingletonAppMutations, installCompatMount } from './compat/global'
-import { installLegacyConfigProperties } from './compat/globalConfig'
-import { installGlobalFilterMethod } from './compat/filter'
+import { installAppCompatProperties } from './compat/global'
 
 export interface App<HostElement = any> {
   version: string
@@ -328,10 +326,7 @@ export function createAppAPI<HostElement>(
     })
 
     if (__COMPAT__) {
-      installCompatMount(app, context, render, hydrate)
-      installGlobalFilterMethod(app, context)
-      if (__DEV__) installLegacyConfigProperties(app.config)
-      applySingletonAppMutations(app)
+      installAppCompatProperties(app, context, render)
     }
 
     return app
index e786cf09814286e21fedf14df47e05ac6faf63ce..9bcace7c4a70186f09d9863acb2b361abcf49bcc 100644 (file)
@@ -97,7 +97,7 @@ export const deprecationData: Record<DeprecationTypes, DeprecationData> = {
   [DeprecationTypes.GLOBAL_PROTOTYPE]: {
     message:
       `Vue.prototype is no longer available in Vue 3. ` +
-      `Use config.globalProperties instead.`,
+      `Use app.config.globalProperties instead.`,
     link: `https://v3.vuejs.org/guide/migration/global-api.html#vue-prototype-replaced-by-config-globalproperties`
   },
 
diff --git a/packages/runtime-core/src/compat/filter.ts b/packages/runtime-core/src/compat/filter.ts
deleted file mode 100644 (file)
index 29a5a3f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-import { App, AppContext } from '../apiCreateApp'
-import { warn } from '../warning'
-import { assertCompatEnabled, DeprecationTypes } from './compatConfig'
-
-export function installGlobalFilterMethod(app: App, context: AppContext) {
-  context.filters = {}
-  app.filter = (name: string, filter?: Function): any => {
-    assertCompatEnabled(DeprecationTypes.FILTERS, null)
-    if (!filter) {
-      return context.filters![name]
-    }
-    if (__DEV__ && context.filters![name]) {
-      warn(`Filter "${name}" has already been registered.`)
-    }
-    context.filters![name] = filter
-    return app
-  }
-}
index 24667066500f89e560a0ba719a9f45a48fe3d7a6..da32009f8c75684e5b2e517808d635b832834c48 100644 (file)
@@ -19,7 +19,6 @@ import {
 import { warn } from '../warning'
 import { cloneVNode, createVNode } from '../vnode'
 import { RootRenderFunction } from '../renderer'
-import { RootHydrateFunction } from '../hydration'
 import {
   App,
   AppConfig,
@@ -41,7 +40,11 @@ import { devtoolsInitApp, devtoolsUnmountApp } from '../devtools'
 import { Directive } from '../directives'
 import { nextTick } from '../scheduler'
 import { version } from '..'
-import { LegacyConfig, legacyOptionMergeStrats } from './globalConfig'
+import {
+  installLegacyConfigProperties,
+  LegacyConfig,
+  legacyOptionMergeStrats
+} from './globalConfig'
 import { LegacyDirective } from './customDirective'
 import {
   warnDeprecation,
@@ -69,7 +72,6 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
   version: string
   config: AppConfig & LegacyConfig
 
-  extend: (options?: ComponentOptions) => CompatVue
   nextTick: typeof nextTick
 
   use(plugin: Plugin, ...options: any[]): CompatVue
@@ -82,6 +84,10 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
 
   compile(template: string): RenderFunction
 
+  /**
+   * @deprecated
+   */
+  extend: (options?: ComponentOptions) => CompatVue
   /**
    * @deprecated Vue 3 no longer needs set() for adding new properties.
    */
@@ -106,6 +112,10 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
    * @internal
    */
   options: ComponentOptions
+  /**
+   * @internal
+   */
+  util: any
   /**
    * @internal
    */
@@ -116,7 +126,7 @@ export let isCopyingConfig = false
 
 // exported only for test
 export let singletonApp: App
-let singletonCtor: Function
+let singletonCtor: CompatVue
 
 // Legacy global Vue constructor
 export function createCompatVue(
@@ -159,12 +169,46 @@ export function createCompatVue(
 
   Vue.version = __VERSION__
   Vue.config = singletonApp.config
-  Vue.nextTick = nextTick
+
+  Vue.use = (p, ...options) => {
+    if (p && isFunction(p.install)) {
+      p.install(Vue as any, ...options)
+    } else if (isFunction(p)) {
+      p(Vue as any, ...options)
+    }
+    return Vue
+  }
+
+  Vue.mixin = m => {
+    singletonApp.mixin(m)
+    return Vue
+  }
+
+  Vue.component = ((name: string, comp: Component) => {
+    if (comp) {
+      singletonApp.component(name, comp)
+      return Vue
+    } else {
+      return singletonApp.component(name)
+    }
+  }) as any
+
+  Vue.directive = ((name: string, dir: Directive | LegacyDirective) => {
+    if (dir) {
+      singletonApp.directive(name, dir as Directive)
+      return Vue
+    } else {
+      return singletonApp.directive(name)
+    }
+  }) as any
+
   Vue.options = { _base: Vue }
 
   let cid = 1
   Vue.cid = cid
 
+  Vue.nextTick = nextTick
+
   const extendCache = new WeakMap()
 
   function extendCtor(this: any, extendOptions: ComponentOptions = {}) {
@@ -243,38 +287,6 @@ export function createCompatVue(
     return reactive(target)
   }
 
-  Vue.use = (p, ...options) => {
-    if (p && isFunction(p.install)) {
-      p.install(Vue as any, ...options)
-    } else if (isFunction(p)) {
-      p(Vue as any, ...options)
-    }
-    return Vue
-  }
-
-  Vue.mixin = m => {
-    singletonApp.mixin(m)
-    return Vue
-  }
-
-  Vue.component = ((name: string, comp: Component) => {
-    if (comp) {
-      singletonApp.component(name, comp)
-      return Vue
-    } else {
-      return singletonApp.component(name)
-    }
-  }) as any
-
-  Vue.directive = ((name: string, dir: Directive | LegacyDirective) => {
-    if (dir) {
-      singletonApp.directive(name, dir as Directive)
-      return Vue
-    } else {
-      return singletonApp.directive(name)
-    }
-  }) as any
-
   Vue.filter = ((name: string, filter?: any) => {
     if (filter) {
       singletonApp.filter!(name, filter)
@@ -309,12 +321,64 @@ export function createCompatVue(
   return Vue
 }
 
-export function applySingletonAppMutations(app: App, Ctor?: Function) {
+export function installAppCompatProperties(
+  app: App,
+  context: AppContext,
+  render: RootRenderFunction
+) {
+  installFilterMethod(app, context)
+
   if (!singletonApp) {
-    // this is the call of creating the singleton itself
+    // this is the call of creating the singleton itself so the rest is
+    // unnecessary
     return
   }
 
+  installCompatMount(app, context, render)
+  installLegacyAPIs(app)
+  applySingletonAppMutations(app)
+  if (__DEV__) installLegacyConfigProperties(app.config)
+}
+
+function installFilterMethod(app: App, context: AppContext) {
+  context.filters = {}
+  app.filter = (name: string, filter?: Function): any => {
+    assertCompatEnabled(DeprecationTypes.FILTERS, null)
+    if (!filter) {
+      return context.filters![name]
+    }
+    if (__DEV__ && context.filters![name]) {
+      warn(`Filter "${name}" has already been registered.`)
+    }
+    context.filters![name] = filter
+    return app
+  }
+}
+
+function installLegacyAPIs(app: App) {
+  // expose global API on app instance for legacy plugins
+  Object.defineProperties(app, {
+    // so that app.use() can work with legacy plugins that extend prototypes
+    prototype: {
+      get() {
+        __DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)
+        return app.config.globalProperties
+      }
+    },
+    nextTick: { value: nextTick },
+    extend: { value: singletonCtor.extend },
+    set: { value: singletonCtor.set },
+    delete: { value: singletonCtor.delete },
+    observable: { value: singletonCtor.observable },
+    util: {
+      get() {
+        return singletonCtor.util
+      }
+    }
+  })
+}
+
+function applySingletonAppMutations(app: App) {
   // copy over asset registries and deopt flag
   ;['mixins', 'components', 'directives', 'filters', 'deopt'].forEach(key => {
     // @ts-ignore
@@ -348,20 +412,27 @@ export function applySingletonAppMutations(app: App, Ctor?: Function) {
     }
   }
   isCopyingConfig = false
-
   applySingletonPrototype(app, singletonCtor)
 }
 
 function applySingletonPrototype(app: App, Ctor: Function) {
   // copy prototype augmentations as config.globalProperties
-  if (isCompatEnabled(DeprecationTypes.GLOBAL_PROTOTYPE, null)) {
-    app.config.globalProperties = Ctor.prototype
+  const enabled = isCompatEnabled(DeprecationTypes.GLOBAL_PROTOTYPE, null)
+  if (enabled) {
+    app.config.globalProperties = Object.create(Ctor.prototype)
   }
   let hasPrototypeAugmentations = false
-  for (const key in Ctor.prototype) {
+  const descriptors = Object.getOwnPropertyDescriptors(Ctor.prototype)
+  for (const key in descriptors) {
     if (key !== 'constructor') {
       hasPrototypeAugmentations = true
-      break
+      if (enabled) {
+        Object.defineProperty(
+          app.config.globalProperties,
+          key,
+          descriptors[key]
+        )
+      }
     }
   }
   if (__DEV__ && hasPrototypeAugmentations) {
@@ -369,11 +440,10 @@ function applySingletonPrototype(app: App, Ctor: Function) {
   }
 }
 
-export function installCompatMount(
+function installCompatMount(
   app: App,
   context: AppContext,
-  render: RootRenderFunction,
-  hydrate?: RootHydrateFunction
+  render: RootRenderFunction
 ) {
   let isMounted = false