export let isCopyingConfig = false
+// exported only for test
+export let singletonApp: App
+let singletonCtor: Function
+
// Legacy global Vue constructor
export function createCompatVue(
- createApp: CreateAppFunction<Element>
+ createApp: CreateAppFunction<Element>,
+ createSingletonApp: CreateAppFunction<Element>
): CompatVue {
- const Vue: CompatVue = function Vue(options: ComponentOptions = {}) {
- return createCompatApp(options, Vue)
- } as any
+ singletonApp = createSingletonApp({})
- const singletonApp = createApp({})
+ const Vue: CompatVue = (singletonCtor = function Vue(
+ options: ComponentOptions = {}
+ ) {
+ return createCompatApp(options, Vue)
+ } as any)
function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)
const app = createApp(options)
- // copy over asset registries and deopt flag
- ;['mixins', 'components', 'directives', 'filters', 'deopt'].forEach(key => {
- // @ts-ignore
- app._context[key] = singletonApp._context[key]
- })
-
- // copy over global config mutations
- isCopyingConfig = true
- for (const key in singletonApp.config) {
- if (key === 'isNativeTag') continue
- if (
- isRuntimeOnly() &&
- (key === 'isCustomElement' || key === 'compilerOptions')
- ) {
- continue
- }
- const val = singletonApp.config[key as keyof AppConfig]
- // @ts-ignore
- app.config[key] = val
-
- // compat for runtime ignoredElements -> isCustomElement
- if (
- key === 'ignoredElements' &&
- isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS, null) &&
- !isRuntimeOnly() &&
- isArray(val)
- ) {
- app.config.compilerOptions.isCustomElement = tag => {
- return val.some(v => (isString(v) ? v === tag : v.test(tag)))
- }
- }
- }
- isCopyingConfig = false
-
- // copy prototype augmentations as config.globalProperties
- if (isCompatEnabled(DeprecationTypes.GLOBAL_PROTOTYPE, null)) {
- app.config.globalProperties = Ctor.prototype
- }
- let hasPrototypeAugmentations = false
- for (const key in Ctor.prototype) {
- if (key !== 'constructor') {
- hasPrototypeAugmentations = true
- break
- }
- }
- if (__DEV__ && hasPrototypeAugmentations) {
- warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)
+ if (Ctor !== Vue) {
+ applySingletonPrototype(app, Ctor)
}
const vm = app._createRoot!(options)
return Vue
}
+export function applySingletonAppMutations(app: App, Ctor?: Function) {
+ if (!singletonApp) {
+ // this is the call of creating the singleton itself
+ return
+ }
+
+ // copy over asset registries and deopt flag
+ ;['mixins', 'components', 'directives', 'filters', 'deopt'].forEach(key => {
+ // @ts-ignore
+ app._context[key] = singletonApp._context[key]
+ })
+
+ // copy over global config mutations
+ isCopyingConfig = true
+ for (const key in singletonApp.config) {
+ if (key === 'isNativeTag') continue
+ if (
+ isRuntimeOnly() &&
+ (key === 'isCustomElement' || key === 'compilerOptions')
+ ) {
+ continue
+ }
+ const val = singletonApp.config[key as keyof AppConfig]
+ // @ts-ignore
+ app.config[key] = val
+
+ // compat for runtime ignoredElements -> isCustomElement
+ if (
+ key === 'ignoredElements' &&
+ isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS, null) &&
+ !isRuntimeOnly() &&
+ isArray(val)
+ ) {
+ app.config.compilerOptions.isCustomElement = tag => {
+ return val.some(v => (isString(v) ? v === tag : v.test(tag)))
+ }
+ }
+ }
+ 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
+ }
+ let hasPrototypeAugmentations = false
+ for (const key in Ctor.prototype) {
+ if (key !== 'constructor') {
+ hasPrototypeAugmentations = true
+ break
+ }
+ }
+ if (__DEV__ && hasPrototypeAugmentations) {
+ warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)
+ }
+}
+
export function installCompatMount(
app: App,
context: AppContext,
deprecationData,
toggleDeprecationWarning
} from '../../runtime-core/src/compat/compatConfig'
+import { singletonApp } from '../../runtime-core/src/compat/global'
+import { createApp } from '../src/esm-index'
beforeEach(() => {
toggleDeprecationWarning(false)
const plain = new Vue() as any
expect(plain.$test).toBeUndefined()
})
+
+ test('should affect apps created via createApp()', () => {
+ Vue.prototype.$test = 1
+ const vm = createApp({
+ template: 'foo'
+ }).mount(document.createElement('div')) as any
+ expect(vm.$test).toBe(1)
+ delete Vue.prototype.$test
+ })
})
describe('GLOBAL_SET/DELETE', () => {
expect(n).toBe(2)
})
})
+
+test('global asset registration should affect apps created via createApp', () => {
+ Vue.component('foo', { template: 'foo' })
+ const vm = createApp({
+ template: '<foo/>'
+ }).mount(document.createElement('div')) as any
+ expect(vm.$el.textContent).toBe('foo')
+ delete singletonApp._context.components.foo
+})