When would coordsAtPos return null

I have some code that looks something like this:

computeLineWidth(line) {
    const endOfLinePos = line.to;
    const endOfLineCoords = this.editorView.coordsAtPos(endOfLinePos);
    const begOfLinePos = line.from;
    const begOfLineCoords = this.editorView.coordsAtPos(begOfLinePos);
    return endOfLineCoords.right - begOfLineCoords.left;

Where line is being obtained by iterating over this.editorView.state.doc.lines within a call to a handler passed to EditorView.updateListener.of. I.e. something like:

handleEditorViewUpdate_(update) {
    if (update.geometryChanged) {
      let maxLineWidth = 0;
        for (let i = 1; i <= this.editorView.state.doc.lines; i++) {
            const line = this.editorView.state.doc.line(i);
            const lineWidth = this.computeLineWidth(line);
            if (lineWidth > maxLineWidth) {
                maxLineWidth = lineWidth;
            }
        }
      ...
    }
}

It seems that sometimes the calls to this.editorView.coordsAtPos within computeLineWidth will return null. Other times all will be well. In both circumstances the line.to and line.from values seem reasonable. So, my question is under what circumstances would calls to coordsAtPos be expected to return null?

As an added note, it appears that this happens when a text is pasted into the editor rather than when code is typed into it. It’s possible that it could happen when text is typed in, but I haven’t seen that happen in my experiments.

Thanks in advance.

-Mark

This will happen for text that is outside of the viewport and not currently being drawn—it’s not in the DOM, so the editor cannot determine a position for it.

That makes sense. My followup question is: what determines when text is outside of the viewport? Or perhaps the real question is what determines the size of the viewport. I’m asking because I’m trying to understand why my code works when:

  1. I am just typing text rather than pasting in text.
    or
  2. I simply return from computeLineWidth when this.editorView.coordsAtPos returns null. In this case even large code pastings work just fine.

For more context, I am embedding an editor view in another object. In case it matters, it is an SVG object within which is a foreignObject which contains an HTML div. That HTML div is the parent of the editor view. For various reasons I do not want my users to have to scroll the code editor. I want the containing objects to be big enough to contain the code. The SVG object, foreign object and HTML div do not automatically resize to fit the contents of the editor view, so I am using the handleEditorViewUpdate_ shown previously to explicitly update the sizes of the various objects that the editor view is contained within. So, for example I have some code like the following in handleEditorViewUpdate_ (in addition to the code I’ve shown above:

    this.size_.height = this.editorView.contentDOM.offsetHeight;
    this.divElement_.style.width = this.size_.width + 'px';
    this.divElement_.style.height = this.size_.height + 'px';
    this.foreignObject_.style.width = this.size_.width + 'px';
    this.foreignObject_.style.height = this.size_.height + 'px';

where this is an object which encapsulates the SVG and has properties for the editor view, div and foreignObject I mentioned earlier.

BTW, if there is a better way to do what I am trying to do, please let me know :wink:

Thanks in advance.

-Mark

Probably because if you’re typing the changes happen inside the viewport, whereas when you paste a bigger chunk of code some of that may end up outside of the viewport.

You’re asking why adding proper handling for a condition that caused a crash before fixes the crash? That seems somewhat obvious.

My question then is what makes that bigger chunk ever be inside the viewport. At some point it does get in the viewport.

Sorry if I was unclear. It not just that it fixes the crash. It’s that my code correctly resizes my objects to contain the entire contents of the editor. Basically, what I am seeing is that my EditorView listener, handleEditorViewUpdate_, gets called multiple times (some asynchronously) for a single paste. Sometimes when it’s called coordsAtPos returns null. My code now basically just ignores those cases. But at some point, coordsAtPos returns valid values for all the lines in the EditorView. Presumably that means that at some point all the lines are in the viewport. It’s mysterious to me, though, why sometimes all the lines are in the viewport but at others they are not. That’s why I asked what causes text to be in or out of the viewport. Afaik, my code doing nothing explicit to alter the size of the viewport.

-Mark

The editor does not render code that is has determined to be out of view (scrolled outside of the window or the editor container). It does this automatically and updates the viewport when the document changes or is scrolled. So anything that’s visible to the user will be inside the viewport, and thus can be measured.

You’ll note that in my code I am adjusting the size of editorView’s containing element according to the editorView’s size (rather than the usual other way around). How could that be working (and it is working) if the viewport is limited to the size of the containing element, as you suggest?

-Mark