From 459afbabbf4129303b98003022aa362434e61880 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Sat, 7 Oct 2023 17:10:57 +0800 Subject: [PATCH 01/11] fix(custom-element): Use asynchronous custom element nesting to avoid errors --- .../__tests__/customElement.spec.ts | 35 +++++++++++++++++++ packages/runtime-dom/src/apiCustomElement.ts | 25 +++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 6ccf02c4fa6..f750a695f54 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -5,11 +5,13 @@ import { h, inject, nextTick, + provide, Ref, ref, renderSlot, VueElement } from '../src' +import { expect } from 'vitest' describe('defineCustomElement', () => { const container = document.createElement('div') @@ -692,5 +694,38 @@ describe('defineCustomElement', () => { `
fallback
` ) }) + + test('async & nested custom elements', async () => { + let fooVal: string | undefined = '' + const E = defineCustomElement( + defineAsyncComponent(() => { + return Promise.resolve({ + setup(props) { + provide('foo', 'foo') + }, + render(this: any) { + return h('div', null, [renderSlot(this.$slots, 'default')]) + } + }) + }) + ) + + const EChild = defineCustomElement({ + setup(props) { + fooVal = inject('foo') + }, + render(this: any) { + return h('div', null, 'child') + } + }) + customElements.define('my-el-async-nested-ce', E) + customElements.define('slotted-child', EChild) + container.innerHTML = `` + + await new Promise(r => setTimeout(r)) + const e = container.childNodes[0] as VueElement + expect(e.shadowRoot!.innerHTML).toBe(`
`) + expect(fooVal).toBe('foo') + }) }) }) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 5662b0b535b..19cffab67c7 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -179,6 +179,7 @@ export class VueElement extends BaseClass { private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] private _ob?: MutationObserver | null = null + private _childResolve: Array<() => void> = [] constructor( private _def: InnerComponentDef, private _props: Record = {}, @@ -275,16 +276,34 @@ export class VueElement extends BaseClass { // apply CSS this._applyStyles(styles) - // initial render this._update() } const asyncDef = (this._def as ComponentOptions).__asyncLoader if (asyncDef) { - asyncDef().then(def => resolve(def, true)) + asyncDef().then(def => { + resolve(def, true) + if (this._childResolve.length > 0) { + this._childResolve.forEach((resolve: () => void) => { + resolve() + }) + } + }) } else { - resolve(this._def) + // When parentNode is a custom element rendered by an asynchronous component, + // it is collected and waits for the asynchronous + // completion before executing the resolve function. + const parentNode = this.parentNode as typeof this + if ( + parentNode && + parentNode._def && + (parentNode._def as ComponentOptions).__asyncLoader + ) { + parentNode._childResolve.push(() => resolve(this._def)) + } else { + resolve(this._def) + } } } From 9fd32acf051d7d283e89f737ae9e6f95db52a283 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Sat, 7 Oct 2023 17:19:44 +0800 Subject: [PATCH 02/11] fix(custom-element): rename variable --- packages/runtime-dom/__tests__/customElement.spec.ts | 1 - packages/runtime-dom/src/apiCustomElement.ts | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index f750a695f54..3a492d90044 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -11,7 +11,6 @@ import { renderSlot, VueElement } from '../src' -import { expect } from 'vitest' describe('defineCustomElement', () => { const container = document.createElement('div') diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 19cffab67c7..b8e2c7a15f6 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -276,6 +276,7 @@ export class VueElement extends BaseClass { // apply CSS this._applyStyles(styles) + // initial render this._update() } @@ -285,8 +286,8 @@ export class VueElement extends BaseClass { asyncDef().then(def => { resolve(def, true) if (this._childResolve.length > 0) { - this._childResolve.forEach((resolve: () => void) => { - resolve() + this._childResolve.forEach((childResolveFn: () => void) => { + childResolveFn() }) } }) From cfea662e6ee377cc519c058e384f83f04957f424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Sat, 7 Oct 2023 20:54:32 +0800 Subject: [PATCH 03/11] chore: updated code --- .../__tests__/customElement.spec.ts | 2 +- packages/runtime-dom/src/apiCustomElement.ts | 73 ++++++++++++------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 3a492d90044..6d761f15bcf 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -719,7 +719,7 @@ describe('defineCustomElement', () => { }) customElements.define('my-el-async-nested-ce', E) customElements.define('slotted-child', EChild) - container.innerHTML = `` + container.innerHTML = `
` await new Promise(r => setTimeout(r)) const e = container.childNodes[0] as VueElement diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index b8e2c7a15f6..0ecb3c89e17 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -179,7 +179,8 @@ export class VueElement extends BaseClass { private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] private _ob?: MutationObserver | null = null - private _childResolve: Array<() => void> = [] + private _childResolve: Array<(parent: typeof this) => void> = [] + private _isCE: boolean = true constructor( private _def: InnerComponentDef, private _props: Record = {}, @@ -248,7 +249,11 @@ export class VueElement extends BaseClass { this._ob.observe(this, { attributes: true }) - const resolve = (def: InnerComponentDef, isAsync = false) => { + const resolve = ( + def: InnerComponentDef, + isAsync = false, + parentCE?: typeof this + ) => { const { props, styles } = def // cast Number-type props set before resolve @@ -278,7 +283,7 @@ export class VueElement extends BaseClass { this._applyStyles(styles) // initial render - this._update() + this._update(parentCE) } const asyncDef = (this._def as ComponentOptions).__asyncLoader @@ -286,22 +291,35 @@ export class VueElement extends BaseClass { asyncDef().then(def => { resolve(def, true) if (this._childResolve.length > 0) { - this._childResolve.forEach((childResolveFn: () => void) => { - childResolveFn() - }) + this._childResolve.forEach( + (childResolveFn: (parent: typeof this) => void) => { + childResolveFn(this) + } + ) } }) } else { // When parentNode is a custom element rendered by an asynchronous component, // it is collected and waits for the asynchronous // completion before executing the resolve function. - const parentNode = this.parentNode as typeof this - if ( - parentNode && - parentNode._def && - (parentNode._def as ComponentOptions).__asyncLoader - ) { - parentNode._childResolve.push(() => resolve(this._def)) + const getParentAsyncCE = (el: typeof this): typeof this | null => { + if ( + el._isCE && + el._def && + (el._def as ComponentOptions).__asyncLoader + ) { + return el + } else if (el.parentNode) { + return getParentAsyncCE(el.parentNode as typeof this) + } else { + return null + } + } + const parentNode = getParentAsyncCE(this) + if (parentNode) { + parentNode._childResolve.push((parent: typeof this) => + resolve(this._def, false, parent) + ) } else { resolve(this._def) } @@ -375,11 +393,11 @@ export class VueElement extends BaseClass { } } - private _update() { - render(this._createVNode(), this.shadowRoot!) + private _update(parentCE?: typeof this) { + render(this._createVNode(parentCE), this.shadowRoot!) } - private _createVNode(): VNode { + private _createVNode(parentCE?: typeof this): VNode { const vnode = createVNode(this._def, extend({}, this._props)) if (!this._instance) { vnode.ce = instance => { @@ -418,16 +436,21 @@ export class VueElement extends BaseClass { } // locate nearest Vue custom element parent for provide/inject - let parent: Node | null = this - while ( - (parent = - parent && (parent.parentNode || (parent as ShadowRoot).host)) - ) { - if (parent instanceof VueElement) { - instance.parent = parent._instance - instance.provides = parent._instance!.provides - break + if (!parentCE) { + let parent: Node | null = this + while ( + (parent = + parent && (parent.parentNode || (parent as ShadowRoot).host)) + ) { + if (parent instanceof VueElement) { + instance.parent = parent._instance + instance.provides = parent._instance!.provides + break + } } + } else { + instance.parent = parentCE._instance + instance.provides = parentCE._instance!.provides } } } From 3f89d3b4980778673005e3c5669b5c53ba6c4c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:05:36 +0800 Subject: [PATCH 04/11] chore: updated code --- .../__tests__/customElement.spec.ts | 39 +++++++ packages/runtime-dom/src/apiCustomElement.ts | 109 ++++++++---------- 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 6d761f15bcf..a4250fbbf2d 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -721,6 +721,45 @@ describe('defineCustomElement', () => { customElements.define('slotted-child', EChild) container.innerHTML = `
` + await new Promise(r => setTimeout(r)) + const e = container.childNodes[0] as VueElement + expect(e.shadowRoot!.innerHTML).toBe(`
`) + expect(fooVal).toBe('foo') + }) + test('async & multiple levels of nested custom elements', async () => { + let fooVal: string | undefined = '' + const E = defineCustomElement( + defineAsyncComponent(() => { + return Promise.resolve({ + setup(props) { + provide('foo', 'foo') + }, + render(this: any) { + return h('div', null, [renderSlot(this.$slots, 'default')]) + } + }) + }) + ) + + const EChild = defineCustomElement({ + render(this: any) { + return h('div', null, [renderSlot(this.$slots, 'default')]) + } + }) + + const EChild2 = defineCustomElement({ + setup(props) { + fooVal = inject('foo') + }, + render(this: any) { + return h('div', null, 'child') + } + }) + customElements.define('my-el-async-nested-m-ce', E) + customElements.define('slotted-child-m', EChild) + customElements.define('slotted-child2-m', EChild2) + container.innerHTML = `
` + await new Promise(r => setTimeout(r)) const e = container.childNodes[0] as VueElement expect(e.shadowRoot!.innerHTML).toBe(`
`) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 0ecb3c89e17..0a57e9fadde 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -179,8 +179,8 @@ export class VueElement extends BaseClass { private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] private _ob?: MutationObserver | null = null - private _childResolve: Array<(parent: typeof this) => void> = [] - private _isCE: boolean = true + private _ce_parent?: VueElement | null = null + private _ce_children?: VueElement[] | null = null constructor( private _def: InnerComponentDef, private _props: Record = {}, @@ -210,7 +210,32 @@ export class VueElement extends BaseClass { if (this._resolved) { this._update() } else { - this._resolveDef() + let parent: Node | null = this + let isParentResolved = true + // Recursively find the parent's custom element and set it to '_ce_parent‘ + while ( + (parent = + parent && (parent.parentNode || (parent as ShadowRoot).host)) + ) { + if (parent instanceof VueElement) { + this._ce_parent = parent as VueElement + // If the parent's custom element is asynchronous or not yet resolved + if ( + (parent._def as ComponentOptions).__asyncLoader || + !parent._resolved + ) { + // Store the current custom element in the parent's _ce_children + // and wait for the parent to be resolved before executing + ;(parent._ce_children || (parent._ce_children = [])).push(this) + isParentResolved = false + } + break + } + } + + if (isParentResolved) { + this._resolveDef() + } } } } @@ -233,8 +258,6 @@ export class VueElement extends BaseClass { * resolve inner component definition (handle possible async component) */ private _resolveDef() { - this._resolved = true - // set initial attrs for (let i = 0; i < this.attributes.length; i++) { this._setAttr(this.attributes[i].name) @@ -249,11 +272,8 @@ export class VueElement extends BaseClass { this._ob.observe(this, { attributes: true }) - const resolve = ( - def: InnerComponentDef, - isAsync = false, - parentCE?: typeof this - ) => { + const resolve = (def: InnerComponentDef, isAsync = false) => { + this._resolved = true const { props, styles } = def // cast Number-type props set before resolve @@ -283,46 +303,20 @@ export class VueElement extends BaseClass { this._applyStyles(styles) // initial render - this._update(parentCE) + this._update() + + // The asynchronous custom element needs to call + // the resolveDef function of the descendant custom element at the end. + if (this._ce_children) { + this._ce_children.forEach(child => child._resolveDef()) + } } const asyncDef = (this._def as ComponentOptions).__asyncLoader if (asyncDef) { - asyncDef().then(def => { - resolve(def, true) - if (this._childResolve.length > 0) { - this._childResolve.forEach( - (childResolveFn: (parent: typeof this) => void) => { - childResolveFn(this) - } - ) - } - }) + asyncDef().then(def => resolve(def, true)) } else { - // When parentNode is a custom element rendered by an asynchronous component, - // it is collected and waits for the asynchronous - // completion before executing the resolve function. - const getParentAsyncCE = (el: typeof this): typeof this | null => { - if ( - el._isCE && - el._def && - (el._def as ComponentOptions).__asyncLoader - ) { - return el - } else if (el.parentNode) { - return getParentAsyncCE(el.parentNode as typeof this) - } else { - return null - } - } - const parentNode = getParentAsyncCE(this) - if (parentNode) { - parentNode._childResolve.push((parent: typeof this) => - resolve(this._def, false, parent) - ) - } else { - resolve(this._def) - } + resolve(this._def) } } @@ -393,11 +387,11 @@ export class VueElement extends BaseClass { } } - private _update(parentCE?: typeof this) { - render(this._createVNode(parentCE), this.shadowRoot!) + private _update() { + render(this._createVNode(), this.shadowRoot!) } - private _createVNode(parentCE?: typeof this): VNode { + private _createVNode(): VNode { const vnode = createVNode(this._def, extend({}, this._props)) if (!this._instance) { vnode.ce = instance => { @@ -435,22 +429,9 @@ export class VueElement extends BaseClass { } } - // locate nearest Vue custom element parent for provide/inject - if (!parentCE) { - let parent: Node | null = this - while ( - (parent = - parent && (parent.parentNode || (parent as ShadowRoot).host)) - ) { - if (parent instanceof VueElement) { - instance.parent = parent._instance - instance.provides = parent._instance!.provides - break - } - } - } else { - instance.parent = parentCE._instance - instance.provides = parentCE._instance!.provides + if (this._ce_parent) { + instance.parent = this._ce_parent._instance + instance.provides = this._ce_parent._instance!.provides } } } From b08616b1a156b75c46194c3d98943ea05b31261f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:15:57 +0800 Subject: [PATCH 05/11] chore: updated code --- packages/runtime-dom/src/apiCustomElement.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 0a57e9fadde..5dd971fc915 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -232,7 +232,6 @@ export class VueElement extends BaseClass { break } } - if (isParentResolved) { this._resolveDef() } From c52fd83fb154d9b5a9e673d5ea5c485bdec90dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:00:28 +0800 Subject: [PATCH 06/11] Update packages/runtime-dom/src/apiCustomElement.ts Co-authored-by: edison --- packages/runtime-dom/src/apiCustomElement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 5dd971fc915..307b2bf0338 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -212,7 +212,7 @@ export class VueElement extends BaseClass { } else { let parent: Node | null = this let isParentResolved = true - // Recursively find the parent's custom element and set it to '_ce_parent‘ + // locate nearest Vue custom element parent and set it to '_ce_parent‘ while ( (parent = parent && (parent.parentNode || (parent as ShadowRoot).host)) From 40636647b8c8a0bfd33ffe081d6fc7bdcbdf83ba Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Fri, 15 Dec 2023 14:58:15 +0800 Subject: [PATCH 07/11] chore: updated code --- packages/runtime-dom/src/apiCustomElement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 612bf4fd3bf..81dc24aa3f2 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -221,7 +221,7 @@ export class VueElement extends BaseClass { this._ce_parent = parent as VueElement // If the parent's custom element is asynchronous or not yet resolved if ( - (parent._def as ComponentOptions).__asyncLoader || + (parent._def as ComponentOptions).__asyncLoader && !parent._resolved ) { // Store the current custom element in the parent's _ce_children From 965c12bd138ff74660d66ea0ca47d48f4001ef33 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Fri, 15 Dec 2023 17:48:14 +0800 Subject: [PATCH 08/11] chore: updated code --- .../__tests__/customElement.spec.ts | 6 ++ packages/runtime-dom/src/apiCustomElement.ts | 55 ++++++++++++++----- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index a4250fbbf2d..12eb66a1775 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -728,6 +728,7 @@ describe('defineCustomElement', () => { }) test('async & multiple levels of nested custom elements', async () => { let fooVal: string | undefined = '' + let barVal: string | undefined = '' const E = defineCustomElement( defineAsyncComponent(() => { return Promise.resolve({ @@ -742,6 +743,9 @@ describe('defineCustomElement', () => { ) const EChild = defineCustomElement({ + setup(props) { + provide('bar', 'bar') + }, render(this: any) { return h('div', null, [renderSlot(this.$slots, 'default')]) } @@ -750,6 +754,7 @@ describe('defineCustomElement', () => { const EChild2 = defineCustomElement({ setup(props) { fooVal = inject('foo') + barVal = inject('bar') }, render(this: any) { return h('div', null, 'child') @@ -764,6 +769,7 @@ describe('defineCustomElement', () => { const e = container.childNodes[0] as VueElement expect(e.shadowRoot!.innerHTML).toBe(`
`) expect(fooVal).toBe('foo') + expect(barVal).toBe('bar') }) }) }) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 81dc24aa3f2..122c21ef5c7 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -179,7 +179,7 @@ export class VueElement extends BaseClass { private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] private _ob?: MutationObserver | null = null - private _ce_parent?: VueElement | null = null + private _ce_parent?: VueElement[] | null = null private _ce_children?: VueElement[] | null = null constructor( private _def: InnerComponentDef, @@ -212,22 +212,46 @@ export class VueElement extends BaseClass { } else { let parent: Node | null = this let isParentResolved = true - // locate nearest Vue custom element parent and set it to '_ce_parent‘ + const isResolved = (parent: VueElement) => { + return ( + !parent._resolved && (parent._def as ComponentOptions).__asyncLoader + ) + } + const setChildToParent = () => { + ;( + (parent as VueElement)._ce_children || + ((parent as VueElement)._ce_children = []) + ).push(this) + isParentResolved = false + } while ( (parent = parent && (parent.parentNode || (parent as ShadowRoot).host)) ) { if (parent instanceof VueElement) { - this._ce_parent = parent as VueElement - // If the parent's custom element is asynchronous or not yet resolved - if ( - (parent._def as ComponentOptions).__asyncLoader && - !parent._resolved - ) { - // Store the current custom element in the parent's _ce_children - // and wait for the parent to be resolved before executing - ;(parent._ce_children || (parent._ce_children = [])).push(this) - isParentResolved = false + // Inherit the ancestor custom element's `_ce_parent` + if (parent._ce_parent) { + this._ce_parent = parent._ce_parent + } else if (!this._ce_parent) { + this._ce_parent = [] + } + // Set the parent custom element of the current custom element + this._ce_parent.push(parent) + + // If the parent custom element is asynchronous and has not been resolved, + // set the current custom element to the parent + if (isResolved(parent)) { + setChildToParent() + } else { + // Traverse the custom elements of ancestors to check whether + // there is an asynchronous parent custom element + // eg. async custom element -> custom element -> ustom element + for (const ancestors of this._ce_parent) { + if (isResolved(ancestors)) { + setChildToParent() + break + } + } } break } @@ -428,9 +452,10 @@ export class VueElement extends BaseClass { } } - if (this._ce_parent) { - instance.parent = this._ce_parent._instance - instance.provides = this._ce_parent._instance!.provides + if (this._ce_parent && this._ce_parent.length) { + const _ce_parent = this._ce_parent.shift()! + instance.parent = _ce_parent._instance + instance.provides = _ce_parent._instance!.provides } } } From 473945ac046cb9bcf944e2f50a87b6fb1e9ce646 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Mon, 18 Dec 2023 11:00:28 +0800 Subject: [PATCH 09/11] chore: updated code --- packages/runtime-dom/src/apiCustomElement.ts | 53 +++++--------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 122c21ef5c7..773052b816b 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -179,7 +179,7 @@ export class VueElement extends BaseClass { private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] private _ob?: MutationObserver | null = null - private _ce_parent?: VueElement[] | null = null + private _ce_parent?: VueElement | null = null private _ce_children?: VueElement[] | null = null constructor( private _def: InnerComponentDef, @@ -212,46 +212,20 @@ export class VueElement extends BaseClass { } else { let parent: Node | null = this let isParentResolved = true - const isResolved = (parent: VueElement) => { - return ( - !parent._resolved && (parent._def as ComponentOptions).__asyncLoader - ) - } - const setChildToParent = () => { - ;( - (parent as VueElement)._ce_children || - ((parent as VueElement)._ce_children = []) - ).push(this) - isParentResolved = false - } + let isAncestors = false while ( (parent = parent && (parent.parentNode || (parent as ShadowRoot).host)) - ) { + ) { if (parent instanceof VueElement) { - // Inherit the ancestor custom element's `_ce_parent` - if (parent._ce_parent) { - this._ce_parent = parent._ce_parent - } else if (!this._ce_parent) { - this._ce_parent = [] - } - // Set the parent custom element of the current custom element - this._ce_parent.push(parent) - - // If the parent custom element is asynchronous and has not been resolved, - // set the current custom element to the parent - if (isResolved(parent)) { - setChildToParent() + // Find the first custom element in the ancestor and set it to `_ce_parent` + !isAncestors && (this._ce_parent = parent as VueElement) + if(!parent._resolved && (parent._def as ComponentOptions).__asyncLoader){ + ;(this._ce_parent!._ce_children || (this._ce_parent!._ce_children = [])).push(this) + isParentResolved = false } else { - // Traverse the custom elements of ancestors to check whether - // there is an asynchronous parent custom element - // eg. async custom element -> custom element -> ustom element - for (const ancestors of this._ce_parent) { - if (isResolved(ancestors)) { - setChildToParent() - break - } - } + isAncestors = true + continue } break } @@ -452,10 +426,9 @@ export class VueElement extends BaseClass { } } - if (this._ce_parent && this._ce_parent.length) { - const _ce_parent = this._ce_parent.shift()! - instance.parent = _ce_parent._instance - instance.provides = _ce_parent._instance!.provides + if (this._ce_parent) { + instance.parent = this._ce_parent._instance + instance.provides = this._ce_parent._instance!.provides } } } From c63a635a053c366360c256791e9714dc31199f28 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:01:31 +0000 Subject: [PATCH 10/11] [autofix.ci] apply automated fixes --- packages/runtime-dom/src/apiCustomElement.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 773052b816b..bf2afbe6d42 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -216,12 +216,18 @@ export class VueElement extends BaseClass { while ( (parent = parent && (parent.parentNode || (parent as ShadowRoot).host)) - ) { + ) { if (parent instanceof VueElement) { // Find the first custom element in the ancestor and set it to `_ce_parent` !isAncestors && (this._ce_parent = parent as VueElement) - if(!parent._resolved && (parent._def as ComponentOptions).__asyncLoader){ - ;(this._ce_parent!._ce_children || (this._ce_parent!._ce_children = [])).push(this) + if ( + !parent._resolved && + (parent._def as ComponentOptions).__asyncLoader + ) { + ;( + this._ce_parent!._ce_children || + (this._ce_parent!._ce_children = []) + ).push(this) isParentResolved = false } else { isAncestors = true From 959ba373cf3c8a87da714f85b8c315189d3ef4d3 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 01:49:22 +0000 Subject: [PATCH 11/11] [autofix.ci] apply automated fixes --- .../runtime-dom/__tests__/customElement.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 475934c177b..a5577dfceed 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -1,4 +1,5 @@ import { + type Ref, type Ref, type VueElement, defineAsyncComponent, @@ -8,7 +9,6 @@ import { inject, nextTick, provide, - Ref, ref, renderSlot, } from '../src' @@ -705,9 +705,9 @@ describe('defineCustomElement', () => { }, render(this: any) { return h('div', null, [renderSlot(this.$slots, 'default')]) - } + }, }) - }) + }), ) const EChild = defineCustomElement({ @@ -716,7 +716,7 @@ describe('defineCustomElement', () => { }, render(this: any) { return h('div', null, 'child') - } + }, }) customElements.define('my-el-async-nested-ce', E) customElements.define('slotted-child', EChild) @@ -738,9 +738,9 @@ describe('defineCustomElement', () => { }, render(this: any) { return h('div', null, [renderSlot(this.$slots, 'default')]) - } + }, }) - }) + }), ) const EChild = defineCustomElement({ @@ -749,7 +749,7 @@ describe('defineCustomElement', () => { }, render(this: any) { return h('div', null, [renderSlot(this.$slots, 'default')]) - } + }, }) const EChild2 = defineCustomElement({ @@ -759,7 +759,7 @@ describe('defineCustomElement', () => { }, render(this: any) { return h('div', null, 'child') - } + }, }) customElements.define('my-el-async-nested-m-ce', E) customElements.define('slotted-child-m', EChild)