DOMException Crash in Caret Split via Premature deleteContents()
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 72/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- typescript
- Ambito
- frontend
Direzione di ricerca
Start in src/components/modules/caret.ts, especially Caret.extractFragmentFromCaretPosition() around lines 197–233, and reproduce the formatted paragraph split described in the issue. Trace the selection and range boundaries through the native-input and contenteditable paths. Done means pressing Enter across the formatting boundary no longer throws a DOMException and the block splits correctly.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
3. DOMException Crash in Caret Split via Premature deleteContents()
📍 Affected Locations
src/components/modules/caret.ts(Lines 197–233)
🔍 Deep Technical Diagnosis
When pressing Enter to split a block, Caret.extractFragmentFromCaretPosition() is called to split content from the caret to the end of the block.
// src/components/modules/caret.ts: Lines 200-231
if (selection.rangeCount) {
const selectRange = selection.getRangeAt(0);
const currentBlockInput = this.Editor.BlockManager.currentBlock.currentInput;
selectRange.deleteContents(); // <-- BUG: Mutates DOM before boundary inspection!
if (currentBlockInput) {
if ($.isNativeInput(currentBlockInput)) {
// ...
} else {
const range = selectRange.cloneRange();
range.selectNodeContents(currentBlockInput);
range.setStart(selectRange.endContainer, selectRange.endOffset); // <-- CRASH!
return range.extractContents();
}
}
}
Why It Crashes:
selectRange.deleteContents()deletes the selected nodes from the document tree.- In browsers (especially Chrome/WebKit), deleting nodes collapses text nodes and can completely remove the
selectRange.endContainernode from the DOM, or reduce its character length belowselectRange.endOffset. - When
range.setStart(selectRange.endContainer, selectRange.endOffset)runs immediately after:- If
endContaineris no longer insidecurrentBlockInput, the browser throws:
DOMException: Failed to execute 'setStart' on 'Range': The node provided is not a child of this node. - If
endOffsetexceeds the remaining text length, the browser throws:
DOMException: Failed to execute 'setStart' on 'Range': The offset is larger than the node's length.
- If
- This completely halts the block-splitting operation and leaves the editor in a corrupt, uneditable state.
🧪 Reproduction Steps
- Insert a paragraph with formatting:
Hello <b>world and extra</b> text. - Select text spanning across the tag boundary: e.g., select from
worldtoextra. - Press
Enter. - Observed: Console throws uncaught
DOMException: Failed to execute 'setStart' on 'Range'. Block does not split.
💡 Proposed Solution & Patch
Clone the boundary points or collapse the range cleanly before extracting contents:
src/components/modules/caret.ts
@@ -201,8 +201,6 @@ export default class Caret extends Module {
const selectRange = selection.getRangeAt(0);
const currentBlockInput = this.Editor.BlockManager.currentBlock.currentInput;
- selectRange.deleteContents();
-
if (currentBlockInput) {
if ($.isNativeInput(currentBlockInput)) {
/**
@@ -213,6 +211,7 @@ export default class Caret extends Module {
const input = currentBlockInput as HTMLInputElement | HTMLTextAreaElement;
const newFragment = document.createDocumentFragment();
+ selectRange.deleteContents();
const inputRemainingText = input.value.substring(0, input.selectionStart);
const fragmentText = input.value.substring(input.selectionStart);
@@ -222,8 +221,11 @@ export default class Caret extends Module {
return newFragment;
} else {
- const range = selectRange.cloneRange();
+ selectRange.deleteContents();
+ const range = document.createRange();
range.selectNodeContents(currentBlockInput);
- range.setStart(selectRange.endContainer, selectRange.endOffset);
+ const safeSelection = Selection.get();
+ const anchorRange = safeSelection.rangeCount ? safeSelection.getRangeAt(0) : selectRange;
+ range.setStart(anchorRange.startContainer, anchorRange.startOffset);
return range.extractContents();
}
- Lingua principale
- TypeScript
- Stelle
- 32k
- Fork
- 2.2k
- Merge medio
- 8h 45m
- PR unite (30g)
- 1
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di codex-team/editor.js
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
codex-team/editor.js#3037 · 1 commento ·
-
Floating Promise Anti-Pattern & Premature Caret in Multi-Block PasteForse già presa @anshurajbisoyi98-ctrl l’ha presa 24 giorni fa. Apertabug good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
codex-team/editor.js#3032 · 1 commento ·
-
Silent Data Loss & Broken Error Contract in Saver.save()Forse già presa @Sion612 l’ha presa 34 giorni fa. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
codex-team/editor.js#3030 ·
-
Complete Omission of block.destroy() in Blocks CollectionForse già presa @Minhal128 l’ha presa 33 giorni fa. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
codex-team/editor.js#3029 ·
-
Bug: Link cannot be removedForse già presa @prathmeshyelne l’ha presa 140 giorni fa. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
codex-team/editor.js#3005 · 1 commento ·
Tutte le issue di codex-team/editor.js
Issue simili
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 Meno di un'ora Idoneità per principianti 80/100
nuxt-content/nuxt-studio#599 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
hurttlocker/o8#4997 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
danielmiessler/LifeOS#2413 ·
I maintainer di solito rispondono entro 3 giorni
-
Plugin: sheet music can't be scrolled by hand before playbackForse già presa @snakajima l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
receptron/jinglescript#51 ·
I maintainer di solito rispondono entro 1 giorno