diff --git a/src/elements/editor.js b/src/elements/editor.js index dbe10de0d..4a7e58251 100644 --- a/src/elements/editor.js +++ b/src/elements/editor.js @@ -317,9 +317,9 @@ export class LexicalEditorElement extends HTMLElement { // Skip if the contenteditable already owns focus — the update would be a // no-op but still triggers a full style/layout pass on pages with large // DOMs. - if (this.#isContentFocused) return - - this.editor.focus(() => this.#onFocus()) + if (this.editor && !this.#isContentFocused) { + this.editor.focus(() => this.#onFocus()) + } } get #isContentFocused() { diff --git a/test/browser/tests/editor/focus.test.js b/test/browser/tests/editor/focus.test.js index d47a29747..6caf9df1a 100644 --- a/test/browser/tests/editor/focus.test.js +++ b/test/browser/tests/editor/focus.test.js @@ -26,4 +26,21 @@ test.describe("Focus", () => { await expect(editor.content).toBeFocused() }) + + test("focus() on an uninitialized editor is a safe no-op", async ({ page }) => { + const thrown = await page.evaluate(async () => { + await customElements.whenDefined("lexxy-editor") + + const editor = document.createElement("lexxy-editor") + + try { + editor.focus() + return null + } catch (error) { + return error.message + } + }) + + expect(thrown).toBeNull() + }) })