import { createRenderer, createHydrationRenderer, warn, RootRenderFunction, CreateAppFunction, Renderer, HydrationRenderer, App, RootHydrateFunction, isRuntimeOnly, DeprecationTypes, compatUtils } 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 } from '@vue/shared' declare module '@vue/reactivity' { export interface RefUnwrapBailTypes { // Note: if updating this, also update `types/refBail.d.ts`. runtimeDOMBailTypes: Node | Window } } const rendererOptions = extend({ patchProp, forcePatchProp }, nodeOps) // lazy create the renderer - this makes core renderer logic tree-shakable // in case the user only imports reactivity utilities from Vue. let renderer: Renderer | HydrationRenderer let enabledHydration = false function ensureRenderer() { return renderer || (renderer = createRenderer(rendererOptions)) } function ensureHydrationRenderer() { renderer = enabledHydration ? renderer : createHydrationRenderer(rendererOptions) enabledHydration = true return renderer as HydrationRenderer } // use explicit type casts here to avoid import() calls in rolled-up d.ts export const render = ((...args) => { ensureRenderer().render(...args) }) as RootRenderFunction export const hydrate = ((...args) => { ensureHydrationRenderer().hydrate(...args) }) as RootHydrateFunction export const createApp = ((...args) => { const app = ensureRenderer().createApp(...args) if (__DEV__) { injectNativeTagCheck(app) injectCustomElementCheck(app) } const { mount } = app app.mount = (containerOrSelector: Element | ShadowRoot | string): any => { const container = normalizeContainer(containerOrSelector) if (!container) return const component = app._component if (!isFunction(component) && !component.render && !component.template) { // __UNSAFE__ // Reason: potential execution of JS expressions in in-DOM template. // The user must make sure the in-DOM template is trusted. If it's // rendered by the server, the template should not contain any user data. component.template = container.innerHTML // 2.x compat check if (__COMPAT__ && __DEV__) { for (let i = 0; i < container.attributes.length; i++) { const attr = container.attributes[i] if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) { compatUtils.warnDeprecation( DeprecationTypes.GLOBAL_MOUNT_CONTAINER, null ) break } } } } // clear content before mounting container.innerHTML = '' const proxy = mount(container, false, container instanceof SVGElement) if (container instanceof Element) { container.removeAttribute('v-cloak') container.setAttribute('data-v-app', '') } return proxy } return app }) as CreateAppFunction export const createSSRApp = ((...args) => { const app = ensureHydrationRenderer().createApp(...args) if (__DEV__) { injectNativeTagCheck(app) injectCustomElementCheck(app) } const { mount } = app app.mount = (containerOrSelector: Element | ShadowRoot | string): any => { const container = normalizeContainer(containerOrSelector) if (container) { return mount(container, true, container instanceof SVGElement) } } return app }) as CreateAppFunction function injectNativeTagCheck(app: App) { // Inject `isNativeTag` // this is used for component name validation (dev only) Object.defineProperty(app.config, 'isNativeTag', { value: (tag: string) => isHTMLTag(tag) || isSVGTag(tag), writable: false }) } // dev only function injectCustomElementCheck(app: App) { if (isRuntimeOnly()) { const value = app.config.isCustomElement Object.defineProperty(app.config, 'isCustomElement', { get() { return value }, set() { warn( `The \`isCustomElement\` config option is only respected when using the runtime compiler.` + `If you are using the runtime-only build, \`isCustomElement\` must be passed to \`@vue/compiler-dom\` in the build setup instead` + `- for example, via the \`compilerOptions\` option in vue-loader: https://vue-loader.vuejs.org/options.html#compileroptions.` ) } }) } } function normalizeContainer( container: Element | ShadowRoot | string ): Element | null { if (isString(container)) { const res = document.querySelector(container) if (__DEV__ && !res) { warn( `Failed to mount app: mount target selector "${container}" returned null.` ) } return res } if ( __DEV__ && container instanceof window.ShadowRoot && container.mode === 'closed' ) { warn( `mounting on a ShadowRoot with \`{mode: "closed"}\` may lead to unpredictable bugs` ) } return container as any } // SFC CSS utilities export { useCssModule } from './helpers/useCssModule' export { useCssVars } from './helpers/useCssVars' // DOM-only components export { Transition, TransitionProps } from './components/Transition' export { TransitionGroup, TransitionGroupProps } from './components/TransitionGroup' // **Internal** DOM-only runtime directive helpers export { vModelText, vModelCheckbox, vModelRadio, vModelSelect, vModelDynamic } from './directives/vModel' export { withModifiers, withKeys } from './directives/vOn' export { vShow } from './directives/vShow' // re-export everything from core // h, Component, reactivity API, nextTick, flags & types export * from '@vue/runtime-core'