]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): ensure exposed methods are accessible from custom elements by...
authorlinzhe <40790268+linzhe141@users.noreply.github.com>
Wed, 23 Jul 2025 00:40:40 +0000 (08:40 +0800)
committerGitHub <noreply@github.com>
Wed, 23 Jul 2025 00:40:40 +0000 (08:40 +0800)
close #13632

packages/runtime-core/src/componentOptions.ts
packages/runtime-dom/__tests__/customElement.spec.ts

index 5db6a0a1760938f27db68cb13d37c14d0708079f..25d21477cfc11832d1c8ce7c59a64177a695707e 100644 (file)
@@ -756,6 +756,7 @@ export function applyOptions(instance: ComponentInternalInstance): void {
         Object.defineProperty(exposed, key, {
           get: () => publicThis[key],
           set: val => (publicThis[key] = val),
+          enumerable: true,
         })
       })
     } else if (!instance.exposed) {
index c44840df5e31d8b38baa6c75c577c1d92b1d233a..07ea091486e5909dde5afeb57a79449f8cd9ad59 100644 (file)
@@ -1402,6 +1402,34 @@ describe('defineCustomElement', () => {
   })
 
   describe('expose', () => {
+    test('expose w/ options api', async () => {
+      const E = defineCustomElement({
+        data() {
+          return {
+            value: 0,
+          }
+        },
+        methods: {
+          foo() {
+            ;(this as any).value++
+          },
+        },
+        expose: ['foo'],
+        render(_ctx: any) {
+          return h('div', null, _ctx.value)
+        },
+      })
+      customElements.define('my-el-expose-options-api', E)
+
+      container.innerHTML = `<my-el-expose-options-api></my-el-expose-options-api>`
+      const e = container.childNodes[0] as VueElement & {
+        foo: () => void
+      }
+      expect(e.shadowRoot!.innerHTML).toBe(`<div>0</div>`)
+      e.foo()
+      await nextTick()
+      expect(e.shadowRoot!.innerHTML).toBe(`<div>1</div>`)
+    })
     test('expose attributes and callback', async () => {
       type SetValue = (value: string) => void
       let fn: MockedFunction<SetValue>