javascript/typescript typedefs lost when webworker times out
See original GitHub issuemonaco-editor version: 0.8.3 (playground) Browser: Chrome 58.0.3029.110 (64-bit) OS: Windows 10
When typescript is set to use commonjs modules, and the additional modules are provided as other editor models, the editor will handle imports correctly up until the typescript worker times out. Once the typescript worker times out, the old models will not be taken into account by the new worker.
To reproduce: Run this in the monaco playground. Mouse over the “typed”, “direct”, and “impl” variables and note that they have typing info. Open the chrome debug console, and make a note that typescript has a web worker present. Move focus back to the playground code window, and go do something else for 5 minutes. After the idle time has been reached, the typescript web worker will be disposed. Note its absence in the debug console. Run the custom “Debug Monaco: get models” action, and note that the models still exist. Try to mouse over the variables again. The webworker will be re-created, but the variables now show up as the “any” type, indicating that the models are being ignored.
const useLanguage = "typescript";
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
"target": monaco.languages.typescript.ScriptTarget.ES5,
"moduleResolution": monaco.languages.typescript.ModuleResolutionKind.Classic,
"module": monaco.languages.typescript.ModuleKind.CommonJS,
"noEmit": true,
"noImplicitAny": true,
"noErrorTruncation": true,
"suppressExcessPropertyErrors": false,
"suppressImplicitAnyIndexErrors": true,
"noLib": true,
"allowJs": true
});
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false
});
function createDef(name, code) {
const mod = monaco.editor.createModel(code, useLanguage, monaco.Uri.file("" + name));
mod.onWillDispose(() => {
console.log("Disposing typedef model", name);
});
}
createDef(
'directmod.d.ts', `
declare module "directmod" {
export = 42;
}
`
);
createDef(
'implicitmod.js', `
/**
*
* @param {string} str - A string
* @returns {number} The length of the string
*/
function someFunc(str) {
return str.length;
}
module.exports = {
someFunc
};
`
);
createDef('typedefmod.d.ts', `
export function foo(): void;
`);
function createModel() {
return monaco.editor.createModel(
`
const typed = require("typedefmod");
const direct = require("directmod");
const impl = require("implicitmod");
a.foo();
b.someFunc();
`,
useLanguage,
monaco.Uri.file("src/usage.js")
);
}
const editor = monaco.editor.create(document.getElementById("container"), {
model: createModel()
});
editor.addAction({
id: "get-models",
label: "Debug Monaco: Get Models",
run: () => {
alert(monaco.editor.getModels().map(x => x.uri.toString()).join("\n"))
}
});
Background: I have multiple commonjs-module javascript libraries that the user can edit. I am trying with reasonable success to enable autocomplete and other typed features by keeping the other libraries around as models. However, after the worker times out, all such typing features are lost and the types revert to “any”.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:10 (5 by maintainers)
Workaround:
Convert all non-editing models to typescriptDefaults.addExtraLib() entries, but still use file URIs for the “fileName” field. This bypasses the model / mirror model synchronization altogether and injects them straight into monaco-typescript’s ts service. Thankfully, monaco-typescript will pass the fileName along to typescript itself, so the commonjs module resolution remains intact.
I did some digging, and I suspect the issue lies with EditorModelManager, specifically the third constructor argument “keepIdleModels”. This controls the presence of a timer that makes it ‘forget’ about a model that has not been touched in a few minutes. However, there is no way to affect its behavior, as EditorWorkerClient._getOrCreateModelManager always passes false for this value.
@skymakerolof
(As a hackaround) I’m overwriting/decorating
EditorWorkerClient.prototype._getOrCreateModelManager
, calling the original function and then modifying the returnedEditorModelManager
instance (set a dummy_checkStopModelSync
function).