[Bug] Semantic validation across multiple editor instances
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?
- [ ] Not reproducible in the monaco editor playground
Monaco Editor Playground Code
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSyntaxValidation: false,
noSemanticValidation: false
})
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
allowJs: true,
checkJs: true,
allowNonTsExtensions: true
})
monaco.editor.create(document.getElementById('container1'), {
model: monaco.editor.createModel('const abc = 1', 'javascript', monaco.Uri.parse('file:///a.js'))
})
monaco.editor.create(document.getElementById('container2'), {
model: monaco.editor.createModel('const abc = 2', 'javascript', monaco.Uri.parse('file:///b.js'))
})
<div id="container1" style="height: 50%"></div>
<div id="container2" style="height: 50%"></div>
Actual Behavior
Both editor instances prompt "Cannot redeclare block-scoped variable 'abc'." error.
Expected Behavior
No error prompt. It should be possible to use variables with the same name in two different files.
Additional Context
No response
Are there any known workarounds for this issue while the bug is not fixed? This bug makes it almost impossible to use multiple code editors in a single page.
Besides that, with some pointers in the right direction, I might be able to submit a PR for this :)
All the typescript related code is here: https://github.com/microsoft/monaco-editor/tree/main/src/language/typescript
Unfortunately, I don't know that code very well.
Having the same issue while having an editor in the UI and trying to validate the syntax of the code in a completely separate model.
I solved this problem with the setting - I marked the modules as isolated in the compiler options:
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
isolatedModules: true,
});
But I'm not sure, if this applies to all issues here.
There is a new moduleDetection option in Typescript 4.7, which should fix the problem when set to force.
But the option isn't present in Monaco's CompilerOptions, despite monaco using ts 5.0.
Plus, when setting it manually it doesn't address the issue:
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
allowJs: true,
checkJs: true,
allowNonTsExtensions: true,
isolatedModules: true,
moduleDetection: 'force'
})
TLDR: Use moduleDetection: 3 as a workaround for now.
I've been digging into the code in Monaco and it seems the compiler options are all passed through, so whether or not the moduleDetection property is in the type shouldn't matter too much, though it would be helpful if it was added.
(Edit: See bottom of this comment – this actually seems quite important after all!)
I also found that when setting the compiler option moduleDetection: "force" using setCompilerOptions, it's ignored, because this error shouldn't be possible in that case:
So trying to figure out why that is, I dug deeper into the language service and I found that it actually uses numeric constants for these options, not strings! So the solution is to set moduleDetection: 3 instead.
Here's the relevant code in the language service that gave me the hint that internally it uses numeric constants:
moduleDetection: {
dependencies: ["module", "target"],
computeValue: (compilerOptions) => {
return compilerOptions.moduleDetection || (computedOptions.module.computeValue(compilerOptions) === 100 /* Node16 */ || computedOptions.module.computeValue(compilerOptions) === 199 /* NodeNext */ ? 3 /* Force */ : 2 /* Auto */);
}
},
It seems as if all other options have enums defined and are type safe so people don't run into this trap, however because the moduleDetection option is not in the CompilerOptions interface, plus there is no ModuleDetectionKind enum, this is very easy to encounter.
Here's another enum similar to this one, as an example, we would just need one that is called ModuleDetectionKind with the three possible cases:
https://github.com/microsoft/monaco-editor/blob/b31d22b9ee8e8081751069dc72d397f782cf8eb5/src/language/typescript/monaco.contribution.ts#L50-L53
I'm facing the same problem in my app where two editors are visible at the same time but should not share any context.
Setting moduleDetection: 3 helps with the Cannot redeclare block-scoped variable error, but I can still define a global variable in one editor like e.g. with
declare global {
var NEW_GLOBAL: string;
}
and the other editor can access said global.
how to make two full isolated and standalone versions of monaco? Is there maybe a way to set different workers for different editors?