]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip(vapor): templateRef adjustments
authorEvan You <evan@vuejs.org>
Thu, 12 Dec 2024 14:34:35 +0000 (22:34 +0800)
committerEvan You <evan@vuejs.org>
Thu, 12 Dec 2024 14:34:35 +0000 (22:34 +0800)
14 files changed:
packages/compiler-vapor/src/generate.ts
packages/compiler-vapor/src/generators/operation.ts
packages/compiler-vapor/src/generators/templateRef.ts
packages/compiler-vapor/src/ir/index.ts
packages/compiler-vapor/src/transform.ts
packages/compiler-vapor/src/transforms/transformTemplateRef.ts
packages/runtime-core/src/helpers/useTemplateRef.ts
packages/runtime-dom/src/modules/style.ts
packages/runtime-vapor/__tests__/apiExpose.spec.ts
packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
packages/runtime-vapor/__tests__/errorHandling.spec.ts
packages/runtime-vapor/src/apiTemplateRef.ts [moved from packages/runtime-vapor/src/dom/templateRef.ts with 74% similarity]
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/index.ts

index a134882351e2f3f95befce7e393cafca91babb3b..5b8edd9ece9bbb462cd3b2c164cde2e2dce3f063 100644 (file)
@@ -16,6 +16,7 @@ import {
   codeFragmentToString,
   genCall,
 } from './generators/utils'
+import { setTemplateRefIdent } from './generators/templateRef'
 
 export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
 
@@ -110,19 +111,21 @@ export function generate(
     ', ',
   )
 
-  if (inline) {
-    // push(`((${signature}) => {`)
-  } else {
+  if (!inline) {
     push(NEWLINE, `export function ${functionName}(${signature}) {`)
   }
 
   push(INDENT_START)
+  if (ir.hasTemplateRef) {
+    push(
+      NEWLINE,
+      `const ${setTemplateRefIdent} = ${context.helper('createTemplateRefSetter')}()`,
+    )
+  }
   push(...genBlockContent(ir.block, context, true))
   push(INDENT_END, NEWLINE)
 
-  if (inline) {
-    // push('})()')
-  } else {
+  if (!inline) {
     push('}')
   }
 
index a82fc6e4d1b17cdcf73e10ede5d26a325b8d09ce..50a307d6798477a1dc2004990fb62c636d931594 100644 (file)
@@ -67,9 +67,14 @@ export function genOperation(
       return genDeclareOldRef(oper)
     case IRNodeTypes.SLOT_OUTLET_NODE:
       return genSlotOutlet(oper, context)
+    case IRNodeTypes.WITH_DIRECTIVE:
+      return [] // TODO
+    default:
+      const exhaustiveCheck: never = oper
+      throw new Error(
+        `Unhandled operation type in genOperation: ${exhaustiveCheck}`,
+      )
   }
-
-  return []
 }
 
 export function genEffects(
index 3de2a96d4946ca71415f8b58eb5e5fb9de9224f7..a4d6d546ed3007f2cda66a7909e2998e22a6bbfd 100644 (file)
@@ -3,16 +3,17 @@ import type { CodegenContext } from '../generate'
 import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
 import { type CodeFragment, NEWLINE, genCall } from './utils'
 
+export const setTemplateRefIdent = `_setTemplateRef`
+
 export function genSetTemplateRef(
   oper: SetTemplateRefIRNode,
   context: CodegenContext,
 ): CodeFragment[] {
-  const { helper } = context
   return [
     NEWLINE,
     oper.effect && `r${oper.element} = `,
     ...genCall(
-      helper('setRef'),
+      setTemplateRefIdent, // will be generated in root scope
       `n${oper.element}`,
       genExpression(oper.value, context),
       oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
index f1ca98325e4e7ef9e355375cdfe7b4658b67b36b..011387f67df87e4b0f3211c0ddc92022f6c4df0a 100644 (file)
@@ -63,6 +63,7 @@ export interface RootIRNode {
   component: Set<string>
   directive: Set<string>
   block: BlockIRNode
+  hasTemplateRef: boolean
 }
 
 export interface IfIRNode extends BaseIRNode {
index 69e681745de363f6cd52bcfd98d5694430374821..3855808998a835798f33b023b956eaba523833be 100644 (file)
@@ -220,6 +220,7 @@ export function transform(
     component: new Set(),
     directive: new Set(),
     block: newBlock(node),
+    hasTemplateRef: false,
   }
 
   const context = new TransformContext(ir, node, options)
index 8dbd9ae73c9c00a7782a283dfec75d721b7197ae..9fa7c09bf58b5d50a7593b3144aff884e10ad252 100644 (file)
@@ -15,6 +15,8 @@ export const transformTemplateRef: NodeTransform = (node, context) => {
   const dir = findProp(node, 'ref', false, true)
   if (!dir) return
 
+  context.ir.hasTemplateRef = true
+
   let value: SimpleExpressionNode
   if (dir.type === NodeTypes.DIRECTIVE) {
     value = dir.exp || normalizeBindShorthand(dir.arg!, context)
index 4cb10ea8139e462c9d9582c62f00531f45563240..9540f25c4df4038fa2ea699ca0e89def08cb56da 100644 (file)
@@ -1,5 +1,5 @@
 import { type ShallowRef, readonly, shallowRef } from '@vue/reactivity'
-import { getCurrentInstance } from '../component'
+import { getCurrentGenericInstance } from '../component'
 import { warn } from '../warning'
 import { EMPTY_OBJ } from '@vue/shared'
 
@@ -8,7 +8,7 @@ export const knownTemplateRefs: WeakSet<ShallowRef> = new WeakSet()
 export function useTemplateRef<T = unknown, Keys extends string = string>(
   key: Keys,
 ): Readonly<ShallowRef<T | null>> {
-  const i = getCurrentInstance()
+  const i = getCurrentGenericInstance()
   const r = shallowRef(null)
   if (i) {
     const refs = i.refs === EMPTY_OBJ ? (i.refs = {}) : i.refs
index ac679e0e33139c3968c25052909b6149140753d4..bcc64c712f0aca0654b6b00b06a733a85953ae2a 100644 (file)
@@ -7,7 +7,8 @@ import {
 } from '../directives/vShow'
 import { CSS_VAR_TEXT } from '../helpers/useCssVars'
 
-type Style = string | Record<string, string | string[]> | null | undefined
+type Style = StyleValue | Record<string, StyleValue | StyleValue[]>
+type StyleValue = string | null | undefined
 
 const displayRE = /(^|;)\s*display\s*:/
 
@@ -70,7 +71,7 @@ const importantRE = /\s*!important$/
 function setStyle(
   style: CSSStyleDeclaration,
   name: string,
-  val: string | string[],
+  val: StyleValue | StyleValue[],
 ) {
   if (isArray(val)) {
     val.forEach(v => setStyle(style, name, v))
index c521c3e397f676525f739689d8485420bad2c783..03a7e75771262a89b47966e4dc4e308f0f58f409 100644 (file)
@@ -1,6 +1,6 @@
 import { ref, shallowRef } from '@vue/reactivity'
 import { type VaporComponentInstance, createComponent } from '../src/component'
-import { setRef } from '../src/dom/templateRef'
+import { setRef } from '../src/apiTemplateRef'
 import { makeRender } from './_utils'
 import { currentInstance } from '@vue/runtime-dom'
 import { defineVaporComponent } from '../src/apiDefineComponent'
@@ -8,7 +8,8 @@ import { defineVaporComponent } from '../src/apiDefineComponent'
 const define = makeRender()
 
 describe('api: expose', () => {
-  test.todo('via setup context + template ref', () => {
+  test('via setup context + template ref', () => {
+    let i: any
     const Child = defineVaporComponent({
       setup(_, { expose }) {
         expose({
@@ -20,19 +21,20 @@ describe('api: expose', () => {
     })
     const childRef = ref()
     define({
-      render: () => {
-        const n0 = createComponent(Child)
+      setup: () => {
+        const n0 = (i = createComponent(Child))
+        setRef(currentInstance as VaporComponentInstance, n0, childRef)
         return n0
       },
     }).render()
 
-    expect(childRef.value).toBeTruthy()
+    expect(childRef.value).toBe(i.exposeProxy)
     expect(childRef.value.foo).toBe(1)
     expect(childRef.value.bar).toBe(2)
     expect(childRef.value.baz).toBeUndefined()
   })
 
-  test.todo('via setup context + template ref (expose empty)', () => {
+  test('via setup context + template ref (expose empty)', () => {
     let childInstance: VaporComponentInstance | null = null
     const Child = defineVaporComponent({
       setup(_) {
@@ -42,14 +44,14 @@ describe('api: expose', () => {
     })
     const childRef = shallowRef()
     define({
-      render: () => {
+      setup: () => {
         const n0 = createComponent(Child)
-        setRef(n0, childRef)
+        setRef(currentInstance as VaporComponentInstance, n0, childRef)
         return n0
       },
     }).render()
 
-    expect(childInstance!.exposed).toBeUndefined()
+    expect(childInstance!.exposed).toBeNull()
     expect(childRef.value).toBe(childInstance!)
   })
 
index 5fc64782e54e303a54e4893af4dc627017d0367b..1b912ed29304d90eb2fd0c125e401493a042540b 100644 (file)
@@ -1,10 +1,10 @@
-import type { NodeRef } from '../../src/dom/templateRef'
+import type { NodeRef } from '../../src/apiTemplateRef'
 import {
   createFor,
   createIf,
+  createTemplateRefSetter,
   insert,
   renderEffect,
-  setRef,
   setText,
   template,
 } from '../../src'
@@ -19,7 +19,7 @@ import {
 
 const define = makeRender()
 
-describe.todo('api: template ref', () => {
+describe('api: template ref', () => {
   test('string ref mount', () => {
     const t0 = template('<div ref="refKey"></div>')
     const el = ref(null)
@@ -31,7 +31,7 @@ describe.todo('api: template ref', () => {
       },
       render() {
         const n0 = t0()
-        setRef(n0 as Element, 'refKey')
+        createTemplateRefSetter()(n0 as Element, 'refKey')
         return n0
       },
     })
@@ -57,7 +57,7 @@ describe.todo('api: template ref', () => {
         const n0 = t0()
         let r0: NodeRef | undefined
         renderEffect(() => {
-          r0 = setRef(n0 as Element, refKey.value, r0)
+          r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
         })
         return n0
       },
@@ -72,7 +72,7 @@ describe.todo('api: template ref', () => {
     expect(fooEl.value).toBe(null)
   })
 
-  it('string ref unmount', async () => {
+  it.todo('string ref unmount', async () => {
     const t0 = template('<div></div>')
     const el = ref(null)
     const toggle = ref(true)
@@ -84,6 +84,7 @@ describe.todo('api: template ref', () => {
         }
       },
       render() {
+        const setRef = createTemplateRefSetter()
         const n0 = createIf(
           () => toggle.value,
           () => {
@@ -109,7 +110,7 @@ describe.todo('api: template ref', () => {
     const { render } = define({
       render() {
         const n0 = t0()
-        setRef(n0 as Element, fn)
+        createTemplateRefSetter()(n0 as Element, fn)
         return n0
       },
     })
@@ -129,7 +130,7 @@ describe.todo('api: template ref', () => {
         const n0 = t0()
         let r0: NodeRef | undefined
         renderEffect(() => {
-          r0 = setRef(n0 as Element, fn.value, r0)
+          r0 = createTemplateRefSetter()(n0 as Element, fn.value, r0)
         })
         return n0
       },
@@ -148,7 +149,7 @@ describe.todo('api: template ref', () => {
     expect(fn2.mock.calls[0][0]).toBe(host.children[0])
   })
 
-  it('function ref unmount', async () => {
+  it.todo('function ref unmount', async () => {
     const fn = vi.fn()
     const toggle = ref(true)
 
@@ -159,7 +160,7 @@ describe.todo('api: template ref', () => {
           () => toggle.value,
           () => {
             const n1 = t0()
-            setRef(n1 as Element, fn)
+            createTemplateRefSetter()(n1 as Element, fn)
             return n1
           },
         )
@@ -185,7 +186,7 @@ describe.todo('api: template ref', () => {
       },
       render() {
         const n0 = t0()
-        setRef(n0 as Element, 'refKey')
+        createTemplateRefSetter()(n0 as Element, 'refKey')
         return n0
       },
     })
@@ -213,9 +214,9 @@ describe.todo('api: template ref', () => {
         const n0 = t0()
         const n1 = t1()
         const n2 = t2()
-        setRef(n0 as Element, 'refKey1')
-        setRef(n1 as Element, 'refKey2')
-        setRef(n2 as Element, 'refKey3')
+        createTemplateRefSetter()(n0 as Element, 'refKey1')
+        createTemplateRefSetter()(n1 as Element, 'refKey2')
+        createTemplateRefSetter()(n2 as Element, 'refKey3')
         return [n0, n1, n2]
       },
     })
@@ -234,7 +235,7 @@ describe.todo('api: template ref', () => {
     const { render } = define({
       render() {
         const n0 = t0()
-        setRef(n0 as Element, el)
+        createTemplateRefSetter()(n0 as Element, el)
         renderEffect(() => {
           setText(n0, el.value && el.value.getAttribute('id'))
         })
@@ -265,10 +266,18 @@ describe.todo('api: template ref', () => {
         let r0: NodeRef | undefined
         let r1: NodeRef | undefined
         renderEffect(() => {
-          r0 = setRef(n0 as Element, refToggle.value ? 'foo' : 'bar', r0)
+          r0 = createTemplateRefSetter()(
+            n0 as Element,
+            refToggle.value ? 'foo' : 'bar',
+            r0,
+          )
         })
         renderEffect(() => {
-          r1 = setRef(n1 as Element, refToggle.value ? 'bar' : 'foo', r1)
+          r1 = createTemplateRefSetter()(
+            n1 as Element,
+            refToggle.value ? 'bar' : 'foo',
+            r1,
+          )
         })
         watchEffect(
           () => {
@@ -297,7 +306,7 @@ describe.todo('api: template ref', () => {
   })
 
   // #1789
-  test('toggle the same ref to different elements', async () => {
+  test.todo('toggle the same ref to different elements', async () => {
     const refToggle = ref(false)
     const spy = vi.fn()
 
@@ -306,6 +315,7 @@ describe.todo('api: template ref', () => {
     const { render } = define({
       render() {
         const instance = currentInstance!
+        const setRef = createTemplateRefSetter()
         const n0 = createIf(
           () => refToggle.value,
           () => {
@@ -341,7 +351,7 @@ describe.todo('api: template ref', () => {
   })
 
   // compiled output of v-for + template ref
-  test('ref in v-for', async () => {
+  test.todo('ref in v-for', async () => {
     const show = ref(true)
     const list = reactive([1, 2, 3])
     const listRefs = ref([])
@@ -359,7 +369,12 @@ describe.todo('api: template ref', () => {
               () => list,
               state => {
                 const n1 = t1()
-                setRef(n1 as Element, listRefs, undefined, true)
+                createTemplateRefSetter()(
+                  n1 as Element,
+                  listRefs,
+                  undefined,
+                  true,
+                )
                 renderEffect(() => {
                   const [item] = state
                   setText(n1, item)
@@ -396,7 +411,7 @@ describe.todo('api: template ref', () => {
     expect(mapRefs()).toMatchObject(['2', '3', '4'])
   })
 
-  test('named ref in v-for', async () => {
+  test.todo('named ref in v-for', async () => {
     const show = ref(true)
     const list = reactive([1, 2, 3])
     const listRefs = ref([])
@@ -417,7 +432,12 @@ describe.todo('api: template ref', () => {
               () => list,
               state => {
                 const n1 = t1()
-                setRef(n1 as Element, 'listRefs', undefined, true)
+                createTemplateRefSetter()(
+                  n1 as Element,
+                  'listRefs',
+                  undefined,
+                  true,
+                )
                 renderEffect(() => {
                   const [item] = state
                   setText(n1, item)
@@ -455,59 +475,67 @@ describe.todo('api: template ref', () => {
   })
 
   // #6697 v-for ref behaves differently under production and development
-  test('named ref in v-for , should be responsive when rendering', async () => {
-    const list = ref([1, 2, 3])
-    const listRefs = ref([])
-
-    const t0 = template('<div><div></div><ul></ul></div>')
-    const t1 = template('<li></li>')
-    const { render } = define({
-      setup() {
-        return { listRefs }
-      },
-      render() {
-        const n0 = t0()
-        const n1 = n0.firstChild
-        const n2 = n1!.nextSibling!
-        const n3 = createFor(
-          () => list.value,
-          state => {
-            const n4 = t1()
-            setRef(n4 as Element, 'listRefs', undefined, true)
-            renderEffect(() => {
-              const [item] = state
-              setText(n4, item)
-            })
-            return n4
-          },
-        )
-        insert(n3, n2 as unknown as ParentNode)
-        renderEffect(() => {
-          setText(n1!, String(listRefs.value))
-        })
-        return n0
-      },
-    })
-
-    const { host } = render()
-
-    await nextTick()
-    expect(String(listRefs.value)).toBe(
-      '[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]',
-    )
-    expect(host.innerHTML).toBe(
-      '<div><div>[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>1</li><li>2</li><li>3</li><!--for--></ul></div>',
-    )
-
-    list.value.splice(0, 1)
-    await nextTick()
-    expect(String(listRefs.value)).toBe(
-      '[object HTMLLIElement],[object HTMLLIElement]',
-    )
-    expect(host.innerHTML).toBe(
-      '<div><div>[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>2</li><li>3</li><!--for--></ul></div>',
-    )
-  })
+  test.todo(
+    'named ref in v-for , should be responsive when rendering',
+    async () => {
+      const list = ref([1, 2, 3])
+      const listRefs = ref([])
+
+      const t0 = template('<div><div></div><ul></ul></div>')
+      const t1 = template('<li></li>')
+      const { render } = define({
+        setup() {
+          return { listRefs }
+        },
+        render() {
+          const n0 = t0()
+          const n1 = n0.firstChild
+          const n2 = n1!.nextSibling!
+          const n3 = createFor(
+            () => list.value,
+            state => {
+              const n4 = t1()
+              createTemplateRefSetter()(
+                n4 as Element,
+                'listRefs',
+                undefined,
+                true,
+              )
+              renderEffect(() => {
+                const [item] = state
+                setText(n4, item)
+              })
+              return n4
+            },
+          )
+          insert(n3, n2 as unknown as ParentNode)
+          renderEffect(() => {
+            setText(n1!, String(listRefs.value))
+          })
+          return n0
+        },
+      })
+
+      const { host } = render()
+
+      await nextTick()
+      expect(String(listRefs.value)).toBe(
+        '[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]',
+      )
+      expect(host.innerHTML).toBe(
+        '<div><div>[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>1</li><li>2</li><li>3</li><!--for--></ul></div>',
+      )
+
+      list.value.splice(0, 1)
+      await nextTick()
+      expect(String(listRefs.value)).toBe(
+        '[object HTMLLIElement],[object HTMLLIElement]',
+      )
+      expect(host.innerHTML).toBe(
+        '<div><div>[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>2</li><li>3</li><!--for--></ul></div>',
+      )
+    },
+  )
 
   // TODO: need to implement Component slots
   // test('string ref inside slots', async () => {
@@ -523,7 +551,7 @@ describe.todo('api: template ref', () => {
   //         spy(this.$refs.foo.tag)
   //       })
   //       const n0 = createComponent(Child)
-  //       setRef(n0, 'foo')
+  //       createTemplateRefSetter()(n0, 'foo')
   //       return n0
   //     },
   //   })
index d0f5d1c4cb142ccab3bd1f73fdb03bb80ad337de..2300cf9ff6e4ed7f5b0413e7b65ab53644b89410 100644 (file)
@@ -9,7 +9,7 @@ import {
 import { createComponent, setRef, template } from '../src'
 import { makeRender } from './_utils'
 import type { VaporComponent } from '../src/component'
-import type { RefEl } from '../src/dom/templateRef'
+import type { RefEl } from '../src/apiTemplateRef'
 
 const define = makeRender()
 
similarity index 74%
rename from packages/runtime-vapor/src/dom/templateRef.ts
rename to packages/runtime-vapor/src/apiTemplateRef.ts
index b17a7eea542311625d719d14d3d8889bf4eb7bf0..1e4984cf286a3d478ad2073dae36d12df4316e03 100644 (file)
@@ -4,7 +4,7 @@ import {
   currentInstance,
   getExposed,
   isVaporComponent,
-} from '../component'
+} from './component'
 import {
   type SchedulerJob,
   callWithErrorHandling,
@@ -23,30 +23,41 @@ import {
 export type NodeRef = string | Ref | ((ref: Element) => void)
 export type RefEl = Element | VaporComponentInstance
 
+export type setRefFn = (
+  el: RefEl,
+  ref: NodeRef,
+  oldRef?: NodeRef,
+  refFor?: boolean,
+) => NodeRef | undefined
+
+export function createTemplateRefSetter(): setRefFn {
+  const instance = currentInstance as VaporComponentInstance
+  return (...args) => setRef(instance, ...args)
+}
+
 /**
  * Function for handling a template ref
  */
 export function setRef(
+  instance: VaporComponentInstance,
   el: RefEl,
   ref: NodeRef,
   oldRef?: NodeRef,
   refFor = false,
 ): NodeRef | undefined {
-  if (!currentInstance || currentInstance.isUnmounted) return
+  if (!instance || instance.isUnmounted) return
 
-  const setupState = currentInstance.setupState || {}
+  const setupState: any = __DEV__ ? instance.setupState || {} : null
   const refValue = isVaporComponent(el) ? getExposed(el) || el : el
 
   const refs =
-    currentInstance.refs === EMPTY_OBJ
-      ? (currentInstance.refs = {})
-      : currentInstance.refs
+    instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
 
   // dynamic ref changed. unset old ref
   if (oldRef != null && oldRef !== ref) {
     if (isString(oldRef)) {
       refs[oldRef] = null
-      if (hasOwn(setupState, oldRef)) {
+      if (__DEV__ && hasOwn(setupState, oldRef)) {
         setupState[oldRef] = null
       }
     } else if (isRef(oldRef)) {
@@ -66,6 +77,7 @@ export function setRef(
     }
 
     invokeRefSetter(refValue)
+    // TODO this gets called repeatedly in renderEffect when it's dynamic ref?
     onScopeDispose(() => invokeRefSetter())
   } else {
     const _isString = isString(ref)
@@ -76,7 +88,7 @@ export function setRef(
       const doSet: SchedulerJob = () => {
         if (refFor) {
           existing = _isString
-            ? hasOwn(setupState, ref)
+            ? __DEV__ && hasOwn(setupState, ref)
               ? setupState[ref]
               : refs[ref]
             : ref.value
@@ -85,7 +97,7 @@ export function setRef(
             existing = [refValue]
             if (_isString) {
               refs[ref] = existing
-              if (hasOwn(setupState, ref)) {
+              if (__DEV__ && hasOwn(setupState, ref)) {
                 setupState[ref] = refs[ref]
                 // if setupState[ref] is a reactivity ref,
                 // the existing will also become reactivity too
@@ -100,7 +112,7 @@ export function setRef(
           }
         } else if (_isString) {
           refs[ref] = refValue
-          if (hasOwn(setupState, ref)) {
+          if (__DEV__ && hasOwn(setupState, ref)) {
             setupState[ref] = refValue
           }
         } else if (_isRef) {
@@ -112,13 +124,14 @@ export function setRef(
       doSet.id = -1
       queuePostFlushCb(doSet)
 
+      // TODO this gets called repeatedly in renderEffect when it's dynamic ref?
       onScopeDispose(() => {
         queuePostFlushCb(() => {
           if (isArray(existing)) {
             remove(existing, refValue)
           } else if (_isString) {
             refs[ref] = null
-            if (hasOwn(setupState, ref)) {
+            if (__DEV__ && hasOwn(setupState, ref)) {
               setupState[ref] = null
             }
           } else if (_isRef) {
@@ -127,7 +140,7 @@ export function setRef(
         })
       })
     } else if (__DEV__) {
-      // warn('Invalid template ref type:', ref, `(${typeof ref})`)
+      warn('Invalid template ref type:', ref, `(${typeof ref})`)
     }
   }
   return ref
index 069bb88b68415bdca8fed4b0babbd2b2959d4293..56203792702b091eadf96fe66023f0887b6af5c8 100644 (file)
@@ -31,6 +31,7 @@ import {
   pauseTracking,
   proxyRefs,
   resetTracking,
+  unref,
 } from '@vue/reactivity'
 import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
 import {
@@ -485,7 +486,9 @@ export function getExposed(
   if (instance.exposed) {
     return (
       instance.exposeProxy ||
-      (instance.exposeProxy = proxyRefs(markRaw(instance.exposed)))
+      (instance.exposeProxy = new Proxy(markRaw(instance.exposed), {
+        get: (target, key) => unref(target[key as any]),
+      }))
     )
   }
 }
index 5435441123bec50bf91ae928b07f88070fe6a31e..f9f2e5253fd40e528002b124004ec206ca64ae79 100644 (file)
@@ -25,4 +25,4 @@ export {
 export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
 export { createIf } from './apiCreateIf'
 export { createFor } from './apiCreateFor'
-export { setRef } from './dom/templateRef'
+export { createTemplateRefSetter } from './apiTemplateRef'