From 6c4bf812cda83fca6aef4e3eb41b6e8e9124b7fa Mon Sep 17 00:00:00 2001 From: Chris LaFreniere <40371649+chlafreniere@users.noreply.github.com> Date: Wed, 20 Apr 2022 17:37:38 -0700 Subject: [PATCH] Notebooks: Preventing "previousSibling of Null" Errors on Cell Selection (#19153) * Defensive programming * PR comments --- .../browser/cellViews/textCell.component.ts | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/sql/workbench/contrib/notebook/browser/cellViews/textCell.component.ts b/src/sql/workbench/contrib/notebook/browser/cellViews/textCell.component.ts index 9d73502445..edb992259d 100644 --- a/src/sql/workbench/contrib/notebook/browser/cellViews/textCell.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/cellViews/textCell.component.ts @@ -212,33 +212,34 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges { this.cellModel.markdownCursorPosition = selection?.getPosition(); } } + const selection = window.getSelection(); + const range = selection?.rangeCount > 0 ? selection.getRangeAt(0) : undefined; // On preview mode change, get the cursor position (get the position only when the selection node is a text node) - if (window.getSelection() && window.getSelection().focusNode?.nodeName === '#text' && window.getSelection().getRangeAt(0)) { - let selection = window.getSelection().getRangeAt(0); + if (selection.focusNode?.nodeName === '#text' && range) { // Check to see if the last cursor position is still the same and skip - if (selection.startOffset !== this.cellModel.richTextCursorPosition?.startOffset) { + if (range.startOffset !== this.cellModel.richTextCursorPosition?.startOffset) { // window.getSelection gives the exact html element and offsets of cursor location // Since we only have the output element reference which is the parent of all html nodes // we iterate through it's child nodes until we get the selection element and store the node indexes // in the startElementNodes and endElementNodes and their offsets respectively. let startElementNodes = []; - let startNode = selection.startContainer; - let endNode = selection.endContainer; - while (startNode !== this.output.nativeElement) { + let startNode = range.startContainer; + let endNode = range.endContainer; + while (startNode && startNode !== this.output.nativeElement) { startElementNodes.push(this.getNodeIndex(startNode)); startNode = startNode.parentNode; } let endElementNodes = []; - while (endNode !== this.output.nativeElement) { + while (endNode && endNode !== this.output.nativeElement) { endElementNodes.push(this.getNodeIndex(endNode)); endNode = endNode.parentNode; } // Create cursor position let cursorPosition: ICaretPosition = { startElementNodes: startElementNodes, - startOffset: selection.startOffset, + startOffset: range.startOffset, endElementNodes: endElementNodes, - endOffset: selection.endOffset + endOffset: range.endOffset }; this.cellModel.richTextCursorPosition = cursorPosition; } @@ -267,8 +268,8 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges { getNodeIndex(n: Node): number { let i = 0; - // walk up the node to the top and get it's index - n = n.previousSibling; + // walk up the node to the top and get its index + n = n?.previousSibling; while (n) { i++; n = n.previousSibling;