Skip to content

Conversation

@bdbch
Copy link
Member

@bdbch bdbch commented Jan 24, 2026

Changes Overview

Fixed Chinese/Japanese/Korean IME (Input Method Editor) input causing crashes in Vue 3 mark views by preventing DOM element destruction during composition events.

Implementation Approach

Added a destroyed flag to VueRenderer following the same pattern used in ReactRenderer (commit d8ca9bf). This prevents race conditions where:

  1. ProseMirror destroys a mark view during IME composition
  2. The VueRenderer calls render(null, el), removing the DOM element
  3. Queued operations try to access the now-null element, causing Cannot read property 'parentNode' of null errors

Key changes:

  • Added destroyed boolean flag to track renderer lifecycle state
  • Guard all rendering operations (render(), updateProps()) with destroyed check
  • Make destroy() idempotent (safe to call multiple times)
  • Prevent rendering after destruction by checking flag in renderComponent()

Testing Done

Unit tests added (packages/vue-3/__tests__/VueMarkViewRenderer.spec.ts):

  • ✅ Rapid content changes without errors (simulates IME behavior)
  • ✅ Multiple destroy calls without errors (idempotency)
  • ✅ Content replacement without errors (mark view recreation)

Full test suite:

  • ✅ All 52 test files passed (490 tests total)
  • ✅ No regressions detected
  • ✅ Lint checks passed

Verification Steps

  1. Checkout this branch and install dependencies
  2. Run tests: pnpm test:unit packages/vue-3/__tests__/VueMarkViewRenderer.spec.ts
  3. Verify all 3 tests pass
  4. For manual testing with IME:
    • Create a Vue 3 editor with a custom mark using VueMarkViewRenderer
    • Add content with marks (e.g., <p>Text <mark>marked text</mark> here</p>)
    • Position cursor inside the mark
    • Switch to Chinese/Japanese/Korean IME input
    • Type characters - the mark should remain intact without errors

Additional Notes

This issue manifests specifically when using VueMarkViewRenderer with IME input methods. The root cause is identical to the React race condition fixed in #7362 (commit d8ca9bf), so this implementation mirrors that proven solution.

Why Vue 2 doesn't need this fix: Vue 2 doesn't have VueMarkViewRenderer - only VueNodeViewRenderer - so it's unaffected by this mark view-specific issue.

Checklist

  • I have created a changeset for this PR if necessary.
  • My changes do not break the library.
  • I have added tests where applicable.
  • I have followed the project guidelines.
  • I have fixed any lint issues.

Related Issues

Fixes #6982

Fixes #6982 by adding a destroyed flag to VueRenderer, similar to the
React implementation. This prevents race conditions when ProseMirror
attempts to access DOM elements during IME composition events (Chinese,
Japanese, Korean input).

The fix ensures that:
- Multiple destroy() calls are idempotent
- No rendering operations occur after destroy is called
- DOM elements remain accessible during composition events

Includes comprehensive unit tests for VueMarkViewRenderer.
Copilot AI review requested due to automatic review settings January 24, 2026 05:56
@changeset-bot
Copy link

changeset-bot bot commented Jan 24, 2026

🦋 Changeset detected

Latest commit: 64c5fed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 72 packages
Name Type
@tiptap/vue-3 Patch
@tiptap/extension-drag-handle-vue-3 Patch
@tiptap/core Patch
@tiptap/extension-audio Patch
@tiptap/extension-blockquote Patch
@tiptap/extension-bold Patch
@tiptap/extension-bubble-menu Patch
@tiptap/extension-bullet-list Patch
@tiptap/extension-code-block-lowlight Patch
@tiptap/extension-code-block Patch
@tiptap/extension-code Patch
@tiptap/extension-collaboration-caret Patch
@tiptap/extension-collaboration Patch
@tiptap/extension-color Patch
@tiptap/extension-details Patch
@tiptap/extension-document Patch
@tiptap/extension-drag-handle-react Patch
@tiptap/extension-drag-handle-vue-2 Patch
@tiptap/extension-drag-handle Patch
@tiptap/extension-emoji Patch
@tiptap/extension-file-handler Patch
@tiptap/extension-floating-menu Patch
@tiptap/extension-font-family Patch
@tiptap/extension-hard-break Patch
@tiptap/extension-heading Patch
@tiptap/extension-highlight Patch
@tiptap/extension-horizontal-rule Patch
@tiptap/extension-image Patch
@tiptap/extension-invisible-characters Patch
@tiptap/extension-italic Patch
@tiptap/extension-link Patch
@tiptap/extension-list Patch
@tiptap/extension-mathematics Patch
@tiptap/extension-mention Patch
@tiptap/extension-node-range Patch
@tiptap/extension-ordered-list Patch
@tiptap/extension-paragraph Patch
@tiptap/extension-strike Patch
@tiptap/extension-subscript Patch
@tiptap/extension-superscript Patch
@tiptap/extension-table-of-contents Patch
@tiptap/extension-table Patch
@tiptap/extension-text-align Patch
@tiptap/extension-text-style Patch
@tiptap/extension-text Patch
@tiptap/extension-twitch Patch
@tiptap/extension-typography Patch
@tiptap/extension-underline Patch
@tiptap/extension-unique-id Patch
@tiptap/extension-youtube Patch
@tiptap/extensions Patch
@tiptap/html Patch
@tiptap/markdown Patch
@tiptap/pm Patch
@tiptap/react Patch
@tiptap/starter-kit Patch
@tiptap/static-renderer Patch
@tiptap/suggestion Patch
@tiptap/vue-2 Patch
@tiptap/extension-character-count Patch
@tiptap/extension-dropcursor Patch
@tiptap/extension-focus Patch
@tiptap/extension-gapcursor Patch
@tiptap/extension-history Patch
@tiptap/extension-list-item Patch
@tiptap/extension-list-keymap Patch
@tiptap/extension-placeholder Patch
@tiptap/extension-table-cell Patch
@tiptap/extension-table-header Patch
@tiptap/extension-table-row Patch
@tiptap/extension-task-item Patch
@tiptap/extension-task-list Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Jan 24, 2026

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit 64c5fed
🔍 Latest deploy log https://app.netlify.com/projects/tiptap-embed/deploys/697464ef2b9c6d0008b61d80
😎 Deploy Preview https://deploy-preview-7450--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a race condition that causes crashes when using IME input (Chinese, Japanese, Korean) in Vue 3 mark views. The issue occurs when ProseMirror destroys a mark view during IME composition, causing queued operations to access a now-null DOM element.

Changes:

  • Added a destroyed flag to VueRenderer to track lifecycle state
  • Guard all rendering operations with destroyed checks to prevent post-destruction operations
  • Made the destroy() method idempotent to safely handle multiple calls
  • Added comprehensive unit tests for IME-related scenarios

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/vue-3/src/VueRenderer.ts Added destroyed flag and guard checks in renderComponent(), updateProps(), and destroy() to prevent race conditions during mark view destruction
packages/vue-3/tests/VueMarkViewRenderer.spec.ts New unit test file with 3 tests covering rapid content changes, multiple destroy calls, and content replacement scenarios
.changeset/fix-chinese-input-ime-vue3.md Changeset documenting the patch-level fix for IME input in Vue 3 mark views

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

bdbch and others added 3 commits January 24, 2026 07:12
- Remove redundant condition checks in renderComponent()
- Add comprehensive unit tests for VueRenderer destroyed flag behavior
- Test idempotent destroy, props updates after destroy, and render blocking
- Verify all 10 tests pass (7 VueRenderer + 3 VueMarkViewRenderer)
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 24, 2026

Open in StackBlitz

@tiptap/core

npm i https://pkg.pr.new/@tiptap/core@7450

@tiptap/extension-blockquote

npm i https://pkg.pr.new/@tiptap/extension-blockquote@7450

@tiptap/extension-audio

npm i https://pkg.pr.new/@tiptap/extension-audio@7450

@tiptap/extension-bold

npm i https://pkg.pr.new/@tiptap/extension-bold@7450

@tiptap/extension-bubble-menu

npm i https://pkg.pr.new/@tiptap/extension-bubble-menu@7450

@tiptap/extension-bullet-list

npm i https://pkg.pr.new/@tiptap/extension-bullet-list@7450

@tiptap/extension-code

npm i https://pkg.pr.new/@tiptap/extension-code@7450

@tiptap/extension-code-block

npm i https://pkg.pr.new/@tiptap/extension-code-block@7450

@tiptap/extension-code-block-lowlight

npm i https://pkg.pr.new/@tiptap/extension-code-block-lowlight@7450

@tiptap/extension-collaboration-caret

npm i https://pkg.pr.new/@tiptap/extension-collaboration-caret@7450

@tiptap/extension-collaboration

npm i https://pkg.pr.new/@tiptap/extension-collaboration@7450

@tiptap/extension-color

npm i https://pkg.pr.new/@tiptap/extension-color@7450

@tiptap/extension-document

npm i https://pkg.pr.new/@tiptap/extension-document@7450

@tiptap/extension-details

npm i https://pkg.pr.new/@tiptap/extension-details@7450

@tiptap/extension-drag-handle

npm i https://pkg.pr.new/@tiptap/extension-drag-handle@7450

@tiptap/extension-drag-handle-vue-2

npm i https://pkg.pr.new/@tiptap/extension-drag-handle-vue-2@7450

@tiptap/extension-drag-handle-react

npm i https://pkg.pr.new/@tiptap/extension-drag-handle-react@7450

@tiptap/extension-drag-handle-vue-3

npm i https://pkg.pr.new/@tiptap/extension-drag-handle-vue-3@7450

@tiptap/extension-file-handler

npm i https://pkg.pr.new/@tiptap/extension-file-handler@7450

@tiptap/extension-emoji

npm i https://pkg.pr.new/@tiptap/extension-emoji@7450

@tiptap/extension-floating-menu

npm i https://pkg.pr.new/@tiptap/extension-floating-menu@7450

@tiptap/extension-hard-break

npm i https://pkg.pr.new/@tiptap/extension-hard-break@7450

@tiptap/extension-font-family

npm i https://pkg.pr.new/@tiptap/extension-font-family@7450

@tiptap/extension-heading

npm i https://pkg.pr.new/@tiptap/extension-heading@7450

@tiptap/extension-highlight

npm i https://pkg.pr.new/@tiptap/extension-highlight@7450

@tiptap/extension-horizontal-rule

npm i https://pkg.pr.new/@tiptap/extension-horizontal-rule@7450

@tiptap/extension-invisible-characters

npm i https://pkg.pr.new/@tiptap/extension-invisible-characters@7450

@tiptap/extension-italic

npm i https://pkg.pr.new/@tiptap/extension-italic@7450

@tiptap/extension-image

npm i https://pkg.pr.new/@tiptap/extension-image@7450

@tiptap/extension-link

npm i https://pkg.pr.new/@tiptap/extension-link@7450

@tiptap/extension-list

npm i https://pkg.pr.new/@tiptap/extension-list@7450

@tiptap/extension-mathematics

npm i https://pkg.pr.new/@tiptap/extension-mathematics@7450

@tiptap/extension-mention

npm i https://pkg.pr.new/@tiptap/extension-mention@7450

@tiptap/extension-node-range

npm i https://pkg.pr.new/@tiptap/extension-node-range@7450

@tiptap/extension-ordered-list

npm i https://pkg.pr.new/@tiptap/extension-ordered-list@7450

@tiptap/extension-paragraph

npm i https://pkg.pr.new/@tiptap/extension-paragraph@7450

@tiptap/extension-strike

npm i https://pkg.pr.new/@tiptap/extension-strike@7450

@tiptap/extension-subscript

npm i https://pkg.pr.new/@tiptap/extension-subscript@7450

@tiptap/extension-superscript

npm i https://pkg.pr.new/@tiptap/extension-superscript@7450

@tiptap/extension-table

npm i https://pkg.pr.new/@tiptap/extension-table@7450

@tiptap/extension-table-of-contents

npm i https://pkg.pr.new/@tiptap/extension-table-of-contents@7450

@tiptap/extension-text

npm i https://pkg.pr.new/@tiptap/extension-text@7450

@tiptap/extension-text-align

npm i https://pkg.pr.new/@tiptap/extension-text-align@7450

@tiptap/extension-twitch

npm i https://pkg.pr.new/@tiptap/extension-twitch@7450

@tiptap/extension-text-style

npm i https://pkg.pr.new/@tiptap/extension-text-style@7450

@tiptap/extension-typography

npm i https://pkg.pr.new/@tiptap/extension-typography@7450

@tiptap/extension-underline

npm i https://pkg.pr.new/@tiptap/extension-underline@7450

@tiptap/extension-unique-id

npm i https://pkg.pr.new/@tiptap/extension-unique-id@7450

@tiptap/extension-youtube

npm i https://pkg.pr.new/@tiptap/extension-youtube@7450

@tiptap/extensions

npm i https://pkg.pr.new/@tiptap/extensions@7450

@tiptap/html

npm i https://pkg.pr.new/@tiptap/html@7450

@tiptap/markdown

npm i https://pkg.pr.new/@tiptap/markdown@7450

@tiptap/react

npm i https://pkg.pr.new/@tiptap/react@7450

@tiptap/pm

npm i https://pkg.pr.new/@tiptap/pm@7450

@tiptap/starter-kit

npm i https://pkg.pr.new/@tiptap/starter-kit@7450

@tiptap/static-renderer

npm i https://pkg.pr.new/@tiptap/static-renderer@7450

@tiptap/suggestion

npm i https://pkg.pr.new/@tiptap/suggestion@7450

@tiptap/vue-2

npm i https://pkg.pr.new/@tiptap/vue-2@7450

@tiptap/vue-3

npm i https://pkg.pr.new/@tiptap/vue-3@7450

@tiptap/extension-character-count

npm i https://pkg.pr.new/@tiptap/extension-character-count@7450

@tiptap/extension-dropcursor

npm i https://pkg.pr.new/@tiptap/extension-dropcursor@7450

@tiptap/extension-focus

npm i https://pkg.pr.new/@tiptap/extension-focus@7450

@tiptap/extension-gapcursor

npm i https://pkg.pr.new/@tiptap/extension-gapcursor@7450

@tiptap/extension-history

npm i https://pkg.pr.new/@tiptap/extension-history@7450

@tiptap/extension-list-item

npm i https://pkg.pr.new/@tiptap/extension-list-item@7450

@tiptap/extension-placeholder

npm i https://pkg.pr.new/@tiptap/extension-placeholder@7450

@tiptap/extension-list-keymap

npm i https://pkg.pr.new/@tiptap/extension-list-keymap@7450

@tiptap/extension-table-cell

npm i https://pkg.pr.new/@tiptap/extension-table-cell@7450

@tiptap/extension-table-header

npm i https://pkg.pr.new/@tiptap/extension-table-header@7450

@tiptap/extension-task-item

npm i https://pkg.pr.new/@tiptap/extension-task-item@7450

@tiptap/extension-table-row

npm i https://pkg.pr.new/@tiptap/extension-table-row@7450

@tiptap/extension-task-list

npm i https://pkg.pr.new/@tiptap/extension-task-list@7450

commit: 64c5fed

@bdbch bdbch merged commit 4807c55 into main Jan 24, 2026
23 checks passed
@bdbch bdbch deleted the claude/fix-chinese-input-LpOln branch January 24, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants