]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: vapor warning context integration
authorEvan You <evan@vuejs.org>
Wed, 4 Dec 2024 02:53:29 +0000 (10:53 +0800)
committerEvan You <evan@vuejs.org>
Wed, 4 Dec 2024 02:53:29 +0000 (10:53 +0800)
packages/runtime-core/src/apiCreateApp.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentEmits.ts
packages/runtime-core/src/index.ts
packages/runtime-core/src/warning.ts
packages/runtime-vapor/src/_new/component.ts
packages/runtime-vapor/src/_new/componentEmits.ts

index e8281bceaa267f4d9ac0e01dd84ef1fc542b323a..4ca4f78da2b84473511258afde9692ebedb75c54 100644 (file)
@@ -120,13 +120,11 @@ export interface App<HostElement = any> {
 
 export type OptionMergeFunction = (to: unknown, from: unknown) => any
 
-export interface AppConfig {
-  // @private
-  readonly isNativeTag: (tag: string) => boolean
-
-  performance: boolean
-  optionMergeStrategies: Record<string, OptionMergeFunction>
-  globalProperties: ComponentCustomProperties & Record<string, any>
+/**
+ * Shared app config between vdom and vapor
+ */
+export interface GenericAppConfig {
+  performance?: boolean
   errorHandler?: (
     err: unknown,
     instance: ComponentPublicInstance | null,
@@ -138,17 +136,6 @@ export interface AppConfig {
     trace: string,
   ) => void
 
-  /**
-   * Options to pass to `@vue/compiler-dom`.
-   * Only supported in runtime compiler build.
-   */
-  compilerOptions: RuntimeCompilerOptions
-
-  /**
-   * @deprecated use config.compilerOptions.isCustomElement
-   */
-  isCustomElement?: (tag: string) => boolean
-
   /**
    * TODO document for 3.5
    * Enable warnings for computed getters that recursively trigger itself.
@@ -168,13 +155,46 @@ export interface AppConfig {
   idPrefix?: string
 }
 
-export interface AppContext {
+export interface AppConfig extends GenericAppConfig {
+  // @private
+  readonly isNativeTag: (tag: string) => boolean
+
+  optionMergeStrategies: Record<string, OptionMergeFunction>
+  globalProperties: ComponentCustomProperties & Record<string, any>
+
+  /**
+   * Options to pass to `@vue/compiler-dom`.
+   * Only supported in runtime compiler build.
+   */
+  compilerOptions: RuntimeCompilerOptions
+
+  /**
+   * @deprecated use config.compilerOptions.isCustomElement
+   */
+  isCustomElement?: (tag: string) => boolean
+}
+
+/**
+ * Minimal app context shared between vdom and vapor
+ */
+export interface GenericAppContext {
   app: App // for devtools
+  config: GenericAppConfig
+  provides: Record<string | symbol, any>
+  components?: Record<string, Component>
+  directives?: Record<string, Directive>
+  /**
+   * HMR only
+   * @internal
+   */
+  reload?: () => void
+}
+
+export interface AppContext extends GenericAppContext {
   config: AppConfig
-  mixins: ComponentOptions[]
   components: Record<string, Component>
   directives: Record<string, Directive>
-  provides: Record<string | symbol, any>
+  mixins: ComponentOptions[]
 
   /**
    * Cache for merged/normalized component options
@@ -193,11 +213,6 @@ export interface AppContext {
    * @internal
    */
   emitsCache: WeakMap<ConcreteComponent, ObjectEmitsOptions | null>
-  /**
-   * HMR only
-   * @internal
-   */
-  reload?: () => void
   /**
    * v2 compat only
    * @internal
index b5cad12eab4d0a34d9d9766a055abfb3ad7e901c..2bac2a3a0c87973afbf7c7f164de0f0d5f953835 100644 (file)
@@ -39,6 +39,7 @@ import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
 import {
   type AppConfig,
   type AppContext,
+  type GenericAppContext,
   createAppContext,
 } from './apiCreateApp'
 import { type Directive, validateDirectiveName } from './directives'
@@ -328,7 +329,7 @@ export interface GenericComponentInstance {
   uid: number
   type: GenericComponent
   parent: GenericComponentInstance | null
-  appContext: AppContext
+  appContext: GenericAppContext
   /**
    * Object containing values this component provides for its descendants
    * @internal
index 6ce9f371a04196e1ef24e97ede4208b830cc3538..c77e8536e6b36f9bdd823cfb5bd1bf08c28ef7d7 100644 (file)
@@ -114,7 +114,6 @@ export function emit(
   event: string,
   ...rawArgs: any[]
 ): ComponentPublicInstance | null | undefined {
-  if (instance.isUnmounted) return
   return baseEmit(
     instance,
     instance.vnode.props || EMPTY_OBJ,
@@ -134,6 +133,7 @@ export function baseEmit(
   event: string,
   ...rawArgs: any[]
 ): ComponentPublicInstance | null | undefined {
+  if (instance.isUnmounted) return
   if (__DEV__) {
     const { emitsOptions, propsOptions } = instance
     if (emitsOptions) {
@@ -173,6 +173,8 @@ export function baseEmit(
   const isModelListener = event.startsWith('update:')
 
   // for v-model update:xxx events, apply modifiers on args
+  // it's ok to use static get because modelModifiers can only be in the static
+  // part of the props
   const modifiers = isModelListener && getModelModifiers(props, event.slice(7))
   if (modifiers) {
     if (modifiers.trim) {
index 53b04b3f3c77ae2f18849e13e403123f9815afc3..dc7f65b34234c5542d1781690b07247fdffabbc4 100644 (file)
@@ -240,6 +240,7 @@ export type {
   App,
   AppConfig,
   AppContext,
+  GenericAppContext,
   Plugin,
   ObjectPlugin,
   FunctionPlugin,
@@ -499,3 +500,4 @@ export {
   type LifecycleHook,
   nextUid,
 } from './component'
+export { pushWarningContext, popWarningContext } from './warning'
index 5ff5f47c6ae428904395a01d99576462a591ea30..cf6003e575fcddda065d67ffdbd98d998ed2845d 100644 (file)
@@ -18,12 +18,18 @@ type TraceEntry = {
 
 type ComponentTraceStack = TraceEntry[]
 
+/**
+ * @internal
+ */
 export function pushWarningContext(
   ctx: GenericComponentInstance | VNode,
 ): void {
   stack.push(ctx)
 }
 
+/**
+ * @internal
+ */
 export function popWarningContext(): void {
   stack.pop()
 }
index c91e54586cf863b3dec3a9a20c687599aa9b82a8..0b47a60982c321525a5401b01b1e61675b6b5f73 100644 (file)
@@ -1,14 +1,16 @@
 import {
-  type AppContext,
   type ComponentInternalOptions,
   type ComponentPropsOptions,
   EffectScope,
   type EmitsOptions,
+  type GenericAppContext,
   type GenericComponentInstance,
   type LifecycleHook,
   type NormalizedPropsOptions,
   type ObjectEmitsOptions,
   nextUid,
+  popWarningContext,
+  pushWarningContext,
 } from '@vue/runtime-core'
 import type { Block } from '../block'
 import type { Data } from '@vue/runtime-shared'
@@ -86,6 +88,10 @@ export function createComponent(
   currentInstance = instance
   instance.scope.on()
 
+  if (__DEV__) {
+    pushWarningContext(instance)
+  }
+
   const setupFn = isFunction(component) ? component : component.setup
   const setupContext = setupFn!.length > 1 ? new SetupContext(instance) : null
   instance.block = setupFn!(
@@ -108,6 +114,10 @@ export function createComponent(
     })
   }
 
+  if (__DEV__) {
+    popWarningContext()
+  }
+
   instance.scope.off()
   currentInstance = prevInstance
   resetTracking()
@@ -116,11 +126,17 @@ export function createComponent(
 
 export let currentInstance: VaporComponentInstance | null = null
 
+const emptyContext: GenericAppContext = {
+  app: null as any,
+  config: {},
+  provides: /*@__PURE__*/ Object.create(null),
+}
+
 export class VaporComponentInstance implements GenericComponentInstance {
   uid: number
   type: VaporComponent
   parent: GenericComponentInstance | null
-  appContext: AppContext
+  appContext: GenericAppContext
 
   block: Block
   scope: EffectScope
@@ -153,8 +169,9 @@ export class VaporComponentInstance implements GenericComponentInstance {
     this.uid = nextUid()
     this.type = comp
     this.parent = currentInstance
-    // @ts-expect-error TODO use proper appContext
-    this.appContext = currentInstance ? currentInstance.appContext : {}
+    this.appContext = currentInstance
+      ? currentInstance.appContext
+      : emptyContext
 
     this.block = null! // to be set
     this.scope = new EffectScope(true)
index 1a4ebbc5118ab50a615d19f72d88452d5e60f185..dfce330992eb37b2f008cb346bfb2eb4db291cc8 100644 (file)
@@ -8,7 +8,7 @@ import {
   type VaporComponentInstance,
   currentInstance,
 } from './component'
-import { NOOP, hasOwn, isArray } from '@vue/shared'
+import { EMPTY_OBJ, NOOP, hasOwn, isArray } from '@vue/shared'
 import { resolveSource } from './componentProps'
 
 /**
@@ -48,9 +48,13 @@ export function emit(
   event: string,
   ...rawArgs: any[]
 ): void {
-  const rawProps = instance.rawProps
-  if (!rawProps || instance.isUnmounted) return
-  baseEmit(instance, rawProps, propGetter, event, ...rawArgs)
+  baseEmit(
+    instance,
+    instance.rawProps || EMPTY_OBJ,
+    propGetter,
+    event,
+    ...rawArgs,
+  )
 }
 
 function propGetter(rawProps: Record<string, any>, key: string) {