microsoft / microsoft/monaco-editor

_foreignProxy from createWebWorker never resolved

Open
#4,460 0 comments 0 reactions 0 assignees View on GitHub

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 };

image

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.