]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat: add useInstanceOption for safer instance access
authordaiwei <daiwei521@126.com>
Thu, 30 Oct 2025 13:34:45 +0000 (21:34 +0800)
committerdaiwei <daiwei521@126.com>
Thu, 30 Oct 2025 13:34:45 +0000 (21:34 +0800)
packages/runtime-core/src/componentCurrentInstance.ts
packages/runtime-core/src/index.ts
packages/runtime-dom/src/apiCustomElement.ts

index 7ac52a2e997182fc0a4ffb5d19698e314e2f3a8b..727958fd84ce797e98049a97dbc3314a0d40b9ea 100644 (file)
@@ -5,6 +5,7 @@ import type {
 } from './component'
 import { currentRenderingInstance } from './componentRenderContext'
 import { type EffectScope, setCurrentScope } from '@vue/reactivity'
+import { warn } from './warning'
 
 /**
  * @internal
@@ -90,3 +91,36 @@ export const setCurrentInstance = (
     simpleSetCurrentInstance(instance)
   }
 }
+
+const internalOptions = ['ce'] as const
+
+/**
+ * @internal
+ */
+export const useInstanceOption = <K extends (typeof internalOptions)[number]>(
+  key: K,
+  silent = false,
+): {
+  hasInstance: boolean
+  value: GenericComponentInstance[K] | undefined
+} => {
+  const instance = getCurrentGenericInstance()
+  if (!instance) {
+    if (__DEV__ && !silent) {
+      warn(`useInstanceOption called without an active component instance.`)
+    }
+    return { hasInstance: false, value: undefined }
+  }
+
+  if (!internalOptions.includes(key)) {
+    if (__DEV__) {
+      warn(
+        `useInstanceOption only accepts ` +
+          ` ${internalOptions.map(k => `'${k}'`).join(', ')} as key, got '${key}'.`,
+      )
+    }
+    return { hasInstance: true, value: undefined }
+  }
+
+  return { hasInstance: true, value: instance[key] }
+}
index be0633548ca2bb21198d1a94a63069eeefe87049..67ff4f0e913fc5b5770d20e0909708bc8fa4830c 100644 (file)
@@ -108,7 +108,7 @@ export { getCurrentInstance } from './component'
 /**
  * @internal
  */
-export { getCurrentGenericInstance } from './component'
+export { useInstanceOption } from './component'
 
 // For raw render function users
 export { h } from './h'
index cf95eb4a805b625553099a21f33a6509bbe8c9c5..d3f8acfea2772ef38f524fe20999eb8e52d4ad0c 100644 (file)
@@ -27,9 +27,9 @@ import {
   type VNodeProps,
   createVNode,
   defineComponent,
-  getCurrentGenericInstance,
   nextTick,
   unref,
+  useInstanceOption,
   warn,
 } from '@vue/runtime-core'
 import {
@@ -804,12 +804,12 @@ export class VueElement extends VueElementBase<
 }
 
 export function useHost(caller?: string): VueElementBase | null {
-  const instance = getCurrentGenericInstance()
-  const el = instance && (instance.ce as VueElementBase)
+  const { hasInstance, value } = useInstanceOption('ce', true)
+  const el = value as VueElementBase
   if (el) {
     return el
   } else if (__DEV__) {
-    if (!instance) {
+    if (!hasInstance) {
       warn(
         `${caller || 'useHost'} called without an active component instance.`,
       )