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', () => {
`
`
)
})
+
+ 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)