diff --git a/.changeset/fix-web-core-lynxview-disconnect.md b/.changeset/fix-web-core-lynxview-disconnect.md new file mode 100644 index 0000000000..2e1ada9719 --- /dev/null +++ b/.changeset/fix-web-core-lynxview-disconnect.md @@ -0,0 +1,5 @@ +--- +"@lynx-js/web-core": patch +--- + +fix: avoid error when LynxView is removed immediately after connected diff --git a/packages/web-platform/web-core/src/apis/LynxView.ts b/packages/web-platform/web-core/src/apis/LynxView.ts index d754e5665b..2a4e8df1ed 100644 --- a/packages/web-platform/web-core/src/apis/LynxView.ts +++ b/packages/web-platform/web-core/src/apis/LynxView.ts @@ -92,7 +92,6 @@ export class LynxView extends HTMLElement { ); #instance?: LynxViewInstance; - #connected = false; #url?: string; /** * @public @@ -414,10 +413,13 @@ export class LynxView extends HTMLElement { * @private */ #render() { - if (!this.#rendering && this.#connected) { + if (!this.#rendering && this.isConnected) { this.#rendering = true; queueMicrotask(() => { this.#rendering = false; + if (!this.isConnected) { + return; + } const ssrData = this.getAttribute('ssr'); if (this.#instance) { this.disconnectedCallback(); @@ -529,7 +531,6 @@ export class LynxView extends HTMLElement { * @private */ connectedCallback() { - this.#connected = true; this.#render(); } } diff --git a/packages/web-platform/web-tests/tests/web-core.test.ts b/packages/web-platform/web-tests/tests/web-core.test.ts index 702d3a5396..2b11987ad1 100644 --- a/packages/web-platform/web-tests/tests/web-core.test.ts +++ b/packages/web-platform/web-tests/tests/web-core.test.ts @@ -713,4 +713,40 @@ test.describe('web core tests', () => { await wait(1000); expect(isSuccess).toBeTruthy(); }); + test('should not throw error when removed immediately after connected', async ({ page }) => { + const errors: Error[] = []; + page.on('pageerror', (err) => { + errors.push(err); + }); + + await goto(page); + + // Evaluate in browser context + await page.evaluate(async () => { + // Verify DOM behavior assumption + const div = document.createElement('div'); + const shadow = div.attachShadow({ mode: 'open' }); + const style = document.createElement('style'); + shadow.appendChild(style); + document.body.appendChild(div); + if (!style.sheet) throw new Error('Sheet should exist when connected'); + + document.body.removeChild(div); + if (style.sheet) { + throw new Error('Sheet should be null when disconnected'); + } + + // Create a new lynx-view + const view = document.createElement('lynx-view'); + // Connect it + document.body.appendChild(view); + // Immediately disconnect it + document.body.removeChild(view); + + // Wait a bit to ensure microtasks run + await new Promise((resolve) => setTimeout(resolve, 100)); + }); + + expect(errors.length).toBe(0); + }); });