microsoft / microsoft/monaco-editor
_foreignProxy from createWebWorker never resolved
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 46.8k
- Forks
- 4.1k
- Avg merge
- 17h 58m
- Merged PRs (30d)
- 1
Description
I still have the following issue from @toonvanstrijp
I'm trying to implement a custom language/worker in combination with react-monaco-editor
This is my webpack config:
entry: {
app: [
// Include an alternative client for WebpackDevServer. A client's job is to
// connect to WebpackDevServer by a socket and get notified about changes.
// When you save a file, the client will either apply hot updates (in case
// of CSS changes), or refresh the page (in case of JS changes). When you
// make a syntax error, this client will display a syntax error overlay.
// Note: instead of the default WebpackDevServer client, we use a custom one
// to bring better experience for Create React App users. You can replace
// the line below with these two lines if you prefer the stock client:
// require.resolve('webpack-dev-server/client') + '?/',
// require.resolve('webpack/hot/dev-server'),
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
// Finally, this is your app's code:
paths.appIndexJs,
// require.resolve('monaco-yaml/out/monaco.contribution'),
// We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh.
].filter(Boolean),
// Package each language's worker and give these filenames in `getWorkerUrl`
// json', 'yaml', 'python', 'markdown
// 'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
// 'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
'yaml.worker': 'monaco-yaml/out/yaml.worker',
},
output: {
globalObject: 'self',
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// TODO: remove this when upgrading to webpack 5
futureEmitAssets: true,
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
Then I use the following react code:
import React, { useRef, useEffect } from 'react';
import './App.css';
import MonacoEditor from 'react-monaco-editor';
import 'monaco-editor';
import 'monaco-yaml/out/monaco.contribution';
// @ts-ignore
// eslint-disable-next-line no-restricted-globals
self.MonacoEnvironment = {
getWorkerUrl: function(moduleId: any, label: any) {
console.log(moduleId, label);
if (label === 'json') {
return '/static/js/json.worker.chunk.js';
}
if (label === 'yaml') {
return '/static/js/yaml.worker.chunk.js';
}
return '/static/js/editor.worker.chunk.js';
},
};
const editorWillMount = (monaco: any) => {
console.log(monaco.languages);
};
const App: React.FC = () => {
const editorRef = useRef<any>(null);
return (
<MonacoEditor
ref={editorRef}
editorWillMount={editorWillMount}
language={'yaml'}
width="100%"
height="100%"
value={'px'}
onChange={value => {
console.log(value);
}}
options={{
formatOnPaste: true,
scrollBeyondLastLine: false,
autoIndent: true,
formatOnType: true,
minimap: { enabled: false },
renderWhitespace: 'all',
automaticLayout: true,
}}
/>
);
};
export default App;
My workerManager.js:
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
var STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min
var WorkerManager = /** @class */ (function() {
function WorkerManager(defaults) {
var _this = this;
this._defaults = defaults;
this._worker = null;
this._idleCheckInterval = setInterval(function() {
return _this._checkIfIdle();
}, 30 * 1000);
this._lastUsedTime = 0;
this._configChangeListener = this._defaults.onDidChange(function() {
return _this._stopWorker();
});
}
WorkerManager.prototype.dispose = function() {
clearInterval(this._idleCheckInterval);
this._configChangeListener.dispose();
this._stopWorker();
};
WorkerManager.prototype.getLanguageServiceWorker = function() {
var _this = this;
var resources = [];
for (var _i = 0; _i < arguments.length; _i++) {
resources[_i] = arguments[_i];
}
var _client;
return this._getClient()
.then(function(client) {
_client = client;
})
.then(function(_) {
return _this._worker.withSyncedResources(resources);
})
.then(function(_) {
return _client;
});
};
WorkerManager.prototype._stopWorker = function() {
if (this._worker) {
this._worker.dispose();
this._worker = null;
}
this._client = null;
};
WorkerManager.prototype._checkIfIdle = function() {
if (!this._worker) {
return;
}
var timePassedSinceLastUsed = Date.now() - this._lastUsedTime;
if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) {
this._stopWorker();
}
};
WorkerManager.prototype._getClient = function() {
this._lastUsedTime = Date.now();
if (!this._client) {
this._worker = monaco.editor.createWebWorker({
// module that exports the create() method and returns a `YAMLWorker` instance
moduleId: 'vs/language/yaml/yamlWorker',
label: this._defaults.languageId,
// passed in to the create() method
createData: {
languageSettings: this._defaults.diagnosticsOptions,
languageId: this._defaults.languageId,
enableSchemaRequest: this._defaults.diagnosticsOptions
.enableSchemaRequest,
},
});
console.log(this._worker);
this._client = this._worker.getProxy();
}
return this._client;
};
return WorkerManager;
})();
export { WorkerManager };

As you can see here the _foreignProxy isn't getting resolved. And I don't know why.
I'm trying to implement the following code monaco-yaml
Originally posted by @toonvanstrijp in https://github.com/microsoft/monaco-editor/issues/1317#issuecomment-543108687
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with workerManager.js and the monaco.editor.createWebWorker call, then trace getProxy() and the unresolved _foreignProxy. Check the webpack worker entry and getWorkerUrl paths shown in the issue against the worker setup used by monaco-yaml. Done means the foreign proxy resolves and the YAML worker functions in the reported React integration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100