index.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import {
  2. type App,
  3. type CreateAppFunction,
  4. type DefineComponent,
  5. DeprecationTypes,
  6. type Directive,
  7. type ElementNamespace,
  8. type HydrationRenderer,
  9. type Renderer,
  10. type RootHydrateFunction,
  11. type RootRenderFunction,
  12. compatUtils,
  13. createHydrationRenderer,
  14. createRenderer,
  15. isRuntimeOnly,
  16. warn,
  17. } from '@vue/runtime-core'
  18. import { nodeOps } from './nodeOps'
  19. import { patchProp } from './patchProp'
  20. export { nodeOps, patchProp }
  21. // Importing from the compiler, will be tree-shaken in prod
  22. import {
  23. NOOP,
  24. extend,
  25. isFunction,
  26. isHTMLTag,
  27. isMathMLTag,
  28. isSVGTag,
  29. isString,
  30. } from '@vue/shared'
  31. import type { TransitionProps } from './components/Transition'
  32. import type { TransitionGroupProps } from './components/TransitionGroup'
  33. import type { vShow } from './directives/vShow'
  34. import type { VOnDirective } from './directives/vOn'
  35. import type { VModelDirective } from './directives/vModel'
  36. /**
  37. * This is a stub implementation to prevent the need to use dom types.
  38. *
  39. * To enable proper types, add `"dom"` to `"lib"` in your `tsconfig.json`.
  40. */
  41. type DomType<T> = typeof globalThis extends { window: unknown } ? T : never
  42. declare module '@vue/reactivity' {
  43. export interface RefUnwrapBailTypes {
  44. runtimeDOMBailTypes: DomType<Node | Window>
  45. }
  46. }
  47. declare module '@vue/runtime-core' {
  48. interface GlobalComponents {
  49. Transition: DefineComponent<TransitionProps>
  50. TransitionGroup: DefineComponent<TransitionGroupProps>
  51. }
  52. interface GlobalDirectives {
  53. vShow: typeof vShow
  54. vOn: VOnDirective
  55. vBind: VModelDirective
  56. vIf: Directive<any, boolean>
  57. vOnce: Directive
  58. vSlot: Directive
  59. }
  60. }
  61. const rendererOptions = /*@__PURE__*/ extend({ patchProp }, nodeOps)
  62. // lazy create the renderer - this makes core renderer logic tree-shakable
  63. // in case the user only imports reactivity utilities from Vue.
  64. let renderer: Renderer<Element | ShadowRoot> | HydrationRenderer
  65. let enabledHydration = false
  66. function ensureRenderer() {
  67. return (
  68. renderer ||
  69. (renderer = createRenderer<Node, Element | ShadowRoot>(rendererOptions))
  70. )
  71. }
  72. function ensureHydrationRenderer() {
  73. renderer = enabledHydration
  74. ? renderer
  75. : createHydrationRenderer(rendererOptions)
  76. enabledHydration = true
  77. return renderer as HydrationRenderer
  78. }
  79. // use explicit type casts here to avoid import() calls in rolled-up d.ts
  80. export const render = ((...args) => {
  81. ensureRenderer().render(...args)
  82. }) as RootRenderFunction<Element | ShadowRoot>
  83. export const hydrate = ((...args) => {
  84. ensureHydrationRenderer().hydrate(...args)
  85. }) as RootHydrateFunction
  86. export const createApp = ((...args) => {
  87. const app = ensureRenderer().createApp(...args)
  88. if (__DEV__) {
  89. injectNativeTagCheck(app)
  90. injectCompilerOptionsCheck(app)
  91. }
  92. const { mount } = app
  93. app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
  94. const container = normalizeContainer(containerOrSelector)
  95. if (!container) return
  96. const component = app._component
  97. if (!isFunction(component) && !component.render && !component.template) {
  98. // __UNSAFE__
  99. // Reason: potential execution of JS expressions in in-DOM template.
  100. // The user must make sure the in-DOM template is trusted. If it's
  101. // rendered by the server, the template should not contain any user data.
  102. component.template = container.innerHTML
  103. // 2.x compat check
  104. if (__COMPAT__ && __DEV__ && container.nodeType === 1) {
  105. for (let i = 0; i < (container as Element).attributes.length; i++) {
  106. const attr = (container as Element).attributes[i]
  107. if (attr.name !== 'v-cloak' && /^(?:v-|:|@)/.test(attr.name)) {
  108. compatUtils.warnDeprecation(
  109. DeprecationTypes.GLOBAL_MOUNT_CONTAINER,
  110. null,
  111. )
  112. break
  113. }
  114. }
  115. }
  116. }
  117. // clear content before mounting
  118. if (container.nodeType === 1) {
  119. container.textContent = ''
  120. }
  121. const proxy = mount(container, false, resolveRootNamespace(container))
  122. if (container instanceof Element) {
  123. container.removeAttribute('v-cloak')
  124. container.setAttribute('data-v-app', '')
  125. }
  126. return proxy
  127. }
  128. return app
  129. }) as CreateAppFunction<Element>
  130. export const createSSRApp = ((...args) => {
  131. const app = ensureHydrationRenderer().createApp(...args)
  132. if (__DEV__) {
  133. injectNativeTagCheck(app)
  134. injectCompilerOptionsCheck(app)
  135. }
  136. const { mount } = app
  137. app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
  138. const container = normalizeContainer(containerOrSelector)
  139. if (container) {
  140. return mount(container, true, resolveRootNamespace(container))
  141. }
  142. }
  143. return app
  144. }) as CreateAppFunction<Element>
  145. function resolveRootNamespace(
  146. container: Element | ShadowRoot,
  147. ): ElementNamespace {
  148. if (container instanceof SVGElement) {
  149. return 'svg'
  150. }
  151. if (
  152. typeof MathMLElement === 'function' &&
  153. container instanceof MathMLElement
  154. ) {
  155. return 'mathml'
  156. }
  157. }
  158. function injectNativeTagCheck(app: App) {
  159. // Inject `isNativeTag`
  160. // this is used for component name validation (dev only)
  161. Object.defineProperty(app.config, 'isNativeTag', {
  162. value: (tag: string) => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag),
  163. writable: false,
  164. })
  165. }
  166. // dev only
  167. function injectCompilerOptionsCheck(app: App) {
  168. if (isRuntimeOnly()) {
  169. const isCustomElement = app.config.isCustomElement
  170. Object.defineProperty(app.config, 'isCustomElement', {
  171. get() {
  172. return isCustomElement
  173. },
  174. set() {
  175. warn(
  176. `The \`isCustomElement\` config option is deprecated. Use ` +
  177. `\`compilerOptions.isCustomElement\` instead.`,
  178. )
  179. },
  180. })
  181. const compilerOptions = app.config.compilerOptions
  182. const msg =
  183. `The \`compilerOptions\` config option is only respected when using ` +
  184. `a build of Vue.js that includes the runtime compiler (aka "full build"). ` +
  185. `Since you are using the runtime-only build, \`compilerOptions\` ` +
  186. `must be passed to \`@vue/compiler-dom\` in the build setup instead.\n` +
  187. `- For vue-loader: pass it via vue-loader's \`compilerOptions\` loader option.\n` +
  188. `- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader\n` +
  189. `- For vite: pass it via @vitejs/plugin-vue options. See https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#example-for-passing-options-to-vuecompiler-sfc`
  190. Object.defineProperty(app.config, 'compilerOptions', {
  191. get() {
  192. warn(msg)
  193. return compilerOptions
  194. },
  195. set() {
  196. warn(msg)
  197. },
  198. })
  199. }
  200. }
  201. function normalizeContainer(
  202. container: Element | ShadowRoot | string,
  203. ): Element | ShadowRoot | null {
  204. if (isString(container)) {
  205. const res = document.querySelector(container)
  206. if (__DEV__ && !res) {
  207. warn(
  208. `Failed to mount app: mount target selector "${container}" returned null.`,
  209. )
  210. }
  211. return res
  212. }
  213. if (
  214. __DEV__ &&
  215. window.ShadowRoot &&
  216. container instanceof window.ShadowRoot &&
  217. container.mode === 'closed'
  218. ) {
  219. warn(
  220. `mounting on a ShadowRoot with \`{mode: "closed"}\` may lead to unpredictable bugs`,
  221. )
  222. }
  223. return container as any
  224. }
  225. // Custom element support
  226. export {
  227. defineCustomElement,
  228. defineSSRCustomElement,
  229. useShadowRoot,
  230. useHost,
  231. VueElement,
  232. type VueElementConstructor,
  233. type CustomElementOptions,
  234. } from './apiCustomElement'
  235. // SFC CSS utilities
  236. export { useCssModule } from './helpers/useCssModule'
  237. export { useCssVars } from './helpers/useCssVars'
  238. // DOM-only components
  239. export { Transition, type TransitionProps } from './components/Transition'
  240. export {
  241. TransitionGroup,
  242. type TransitionGroupProps,
  243. } from './components/TransitionGroup'
  244. // **Internal** DOM-only runtime directive helpers
  245. export {
  246. vModelText,
  247. vModelCheckbox,
  248. vModelRadio,
  249. vModelSelect,
  250. vModelDynamic,
  251. } from './directives/vModel'
  252. export { withModifiers, withKeys } from './directives/vOn'
  253. export { vShow } from './directives/vShow'
  254. import { initVModelForSSR } from './directives/vModel'
  255. import { initVShowForSSR } from './directives/vShow'
  256. let ssrDirectiveInitialized = false
  257. /**
  258. * @internal
  259. */
  260. export const initDirectivesForSSR: () => void = __SSR__
  261. ? () => {
  262. if (!ssrDirectiveInitialized) {
  263. ssrDirectiveInitialized = true
  264. initVModelForSSR()
  265. initVShowForSSR()
  266. }
  267. }
  268. : NOOP
  269. // re-export everything from core
  270. // h, Component, reactivity API, nextTick, flags & types
  271. export * from '@vue/runtime-core'
  272. export * from './jsx'