From 3907daba1c3892cf4537b3b0b9a56517d6523bd1 Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 8 Oct 2024 20:43:23 +0800 Subject: [PATCH 1/3] feat(customElement): support attachInternals method --- .../runtime-dom/__tests__/customElement.spec.ts | 14 ++++++++++++++ packages/runtime-dom/src/apiCustomElement.ts | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index ef5051f42f7..b1b740d712e 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -1386,4 +1386,18 @@ describe('defineCustomElement', () => { await nextTick() expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`) }) + + test('support attachInternals method', () => { + const E = defineCustomElement({ + formAssociated: true, + render() { + return h('div', 'hello') + }, + }) + customElements.define('my-el-attach-internals', E) + container.innerHTML = `` + const e = container.childNodes[0] as VueElement + expect(e.shadowRoot!.innerHTML).toBe(`
hello
`) + expect(e._internals).toBeTruthy() + }) }) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 6ddaf897130..bbabda955f5 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -176,6 +176,8 @@ export function defineCustomElement( if (isPlainObject(Comp)) extend(Comp, extraOptions) class VueCustomElement extends VueElement { static def = Comp + static formAssociated = !!options.formAssociated + constructor(initialProps?: Record) { super(Comp, initialProps, _createApp) } @@ -204,6 +206,7 @@ export class VueElement implements ComponentCustomElementInterface { _isVueCE = true + _internals: ElementInternals | null = null /** * @internal */ @@ -253,6 +256,9 @@ export class VueElement private _createApp: CreateAppFunction = createApp, ) { super() + + if (this.attachInternals) this._internals = this.attachInternals() + if (this.shadowRoot && _createApp !== createApp) { this._root = this.shadowRoot } else { From 77922fbb25c44a602cd43d741e10276bc26a93d1 Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 17 Oct 2024 11:28:42 +0800 Subject: [PATCH 2/3] chore: add useHostInternals --- .../runtime-dom/__tests__/customElement.spec.ts | 16 ++++++++++++++++ packages/runtime-dom/src/apiCustomElement.ts | 9 +++++++++ packages/runtime-dom/src/index.ts | 1 + 3 files changed, 26 insertions(+) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index b1b740d712e..cdfcd602152 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -17,6 +17,7 @@ import { render, renderSlot, useHost, + useHostInternals, useShadowRoot, } from '../src' @@ -1132,6 +1133,21 @@ describe('defineCustomElement', () => { const style = el.shadowRoot?.querySelector('style')! expect(style.textContent).toBe(`div { color: red; }`) }) + + // wait for jsdom to fix https://github.com/jsdom/jsdom/issues/3732 + test.todo('useHostInternals', async () => { + const Foo = defineCustomElement({ + setup() { + const internals = useHostInternals()! + internals.ariaLive = 'polite' + return () => h('div', 'hello') + }, + }) + customElements.define('my-el-use-host-internals', Foo) + container.innerHTML = `` + const el = container.childNodes[0] as VueElement + expect(el._internals?.ariaLive).toBe('polite') + }) }) describe('expose', () => { diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index bbabda955f5..24242573058 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -713,3 +713,12 @@ export function useShadowRoot(): ShadowRoot | null { const el = __DEV__ ? useHost('useShadowRoot') : useHost() return el && el.shadowRoot } + +/** + * Retrieve the ElementInternals of the current custom element. Only usable in setup() + * of a `defineCustomElement` component. + */ +export function useHostInternals(): ElementInternals | null { + const el = __DEV__ ? useHost('useHostInternals') : useHost() + return el && el._internals +} diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index ca9a307dd98..b388eac11ec 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -256,6 +256,7 @@ export { defineSSRCustomElement, useShadowRoot, useHost, + useHostInternals, VueElement, type VueElementConstructor, type CustomElementOptions, From 580c3de64b6e205e34faaac6c6ebccbb99ce9632 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 03:47:02 +0000 Subject: [PATCH 3/3] [autofix.ci] apply automated fixes --- packages/runtime-dom/__tests__/customElement.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 6f19ce08e82..69179276999 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -1416,7 +1416,7 @@ describe('defineCustomElement', () => { expect(e.shadowRoot!.innerHTML).toBe(`
hello
`) expect(e._internals).toBeTruthy() }) - + test('hyphenated attr removal', async () => { const E = defineCustomElement({ props: {