monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

[Bug] error when selecting text with mouse in shadow dom

Open hungtcs opened this issue 1 year ago • 5 comments

Reproducible in vscode.dev or in VS Code Desktop?

  • [X] Not reproducible in vscode.dev or VS Code Desktop

Reproducible in the monaco editor playground?

Monaco Editor Playground Link

Link To Monaco Playground

Monaco Editor Playground Code

const defaultValue = `async function main() {
  // select this text with the mouse and an error will appear in the console
}
main().catch((err) => console.error(err))
`;

class MyElement extends HTMLElement {
	constructor() {
		super();
		const shadowRoot = this.attachShadow({ mode: "open" });
		const styleLink = document.createElement('link');
		styleLink.rel ='stylesheet';
		styleLink.href = 'node_modules/monaco-editor/min/vs/editor/editor.main.css'
		shadowRoot.appendChild(styleLink);
	}

	connectedCallback() {
		const conatiner = document.createElement("div");
		conatiner.style.width ='100%'
		conatiner.style.height ='320px'
		conatiner.style.resize ='both'
		conatiner.style.overflow ='hidden'
		this.shadowRoot?.appendChild(conatiner);
		
		monaco.editor.create(conatiner, {
			value: defaultValue,
			theme: 'vs-dark',
			language: "javascript",
			automaticLayout: true,
		});
	}
}

customElements.define('my-element', MyElement);

Reproduction Steps

  1. Select the text in editor with the mouse
  2. An error will appear in the console

Actual (Problematic) Behavior

An error occurred in the console

image

Expected Behavior

No response

Additional Context

No response

hungtcs avatar Jun 04 '24 06:06 hungtcs

The method can be traced through the stack

function shadowCaretRangeFromPoint(shadowRoot, x, y) {
    const range = document.createRange();
    // Get the element under the point
    let el = shadowRoot.elementFromPoint(x, y);
    if (el !== null) {
        // parameter 1 is not of type 'Node'.                       // <---
        range.setStart(el.firstChild, offset);
        range.setEnd(el.firstChild, offset);
    }
    return range;
}

hungtcs avatar Jun 04 '24 06:06 hungtcs

We ran into the same issue: v0.47.0 is the last version to work correctly.

dominik1996 avatar Jun 13 '24 11:06 dominik1996

We ran into the same issue: v0.47.0 is the last version to work correctly.

thanks a lot ,it's worked!

unitsung avatar Jul 12 '24 09:07 unitsung

I am seeing the same issue in our application (v 0.51.0).

ppc-harmoney avatar Sep 06 '24 09:09 ppc-harmoney

seeing the same issue on v0.51.0 too

bagool185 avatar Oct 09 '24 10:10 bagool185

I observed the error when you click on the cursor. It is expecting the div representing the cursor to have a non-null firstChild, causing the error.

The error is still happening in older versions of Monaco, but it is being caught and not surfaced. But, in the newer versions, the catch code re-throws the error causing it to now be visible. The reason for the re-throw appears to be that before this.target was null, but now it is a lazily loaded value, so trying to access this.target in the catch clause re-throws the error.

Is there any workaround? And can this please be fixed in the official code? (Probably a check that el.firstChild is non-null is sufficient.)

Adding error text here for easier searchability
► Uncaught editor.main.js:129132
TypeError: Failed to execute 'setStart' on 'Range': parameter 1 is not of type 'Node'.
  at shadowCaretRangeFromPoint (editor.main.js:129132:19)
  at MouseTargetFactory._actualDoHitTestWithCaretRangeFromPoint (editor.main.js:128973:29)
  at MouseTargetFactory._doHitTestWithCaretRangeFromPoint (editor.main.js:128960:32)
  at MouseTargetFactory.doHitTest (editor.main.js:129065:31)
  at Lazy.executor (editor.main.js:128559:75)
  at get value (editor.main.js:5353:40)
  at get target (editor.main.js:128546:43)
  at MouseTargetFactory._createMouseTarget (editor.main.js:128662:25) MouseTargetFactory.createMouseTarget (editor.main.js:128643:46)
  at TouchHandler._createMouseTarget (editor.main.js:129320:44)

alexander-zw avatar Feb 05 '25 00:02 alexander-zw

Fixed this by doing a Yarn patch, to add an additional try/catch inside the clause in the method createMouseTarget in vscode/src/vs/editor/browser/controller/mouseTarget.js. This prevents the error from surfacing, catching the error in the catch clause. I made the new catch clause return {}; because subsequent code fetches .position on the return value, and returning an object ensures this does not error.

But this should really be fixed in Monaco.

alexander-zw avatar Mar 20 '25 23:03 alexander-zw