mirror of https://github.com/microsoft/vscode.git
Split up the editor's worker and the editor worker helper scripts, remove AMD support
This commit is contained in:
parent
91f0cb7b90
commit
46035d0296
|
@ -44,7 +44,7 @@ export = new class implements eslint.Rule.RuleModule {
|
|||
readonly meta: eslint.Rule.RuleMetaData = {
|
||||
messages: {
|
||||
badImport: 'Imports violates \'{{restrictions}}\' restrictions. See https://github.com/microsoft/vscode/wiki/Source-Code-Organization',
|
||||
badFilename: 'Missing definition in `code-import-patterns` for this file. Define rules at https://github.com/microsoft/vscode/blob/main/.eslintrc.json',
|
||||
badFilename: 'Missing definition in `code-import-patterns` for this file. Define rules at https://github.com/microsoft/vscode/blob/main/eslint.config.js',
|
||||
badAbsolute: 'Imports have to be relative to support ESM',
|
||||
badExtension: 'Imports have to end with `.js` or `.css` to support ESM',
|
||||
},
|
||||
|
|
|
@ -24,7 +24,7 @@ export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule
|
|||
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker.start/.test(fileName)
|
||||
) {
|
||||
return createImportRuleListener((node, path) => {
|
||||
// resolve relative paths
|
||||
|
|
|
@ -38,7 +38,7 @@ export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule
|
|||
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker.start/.test(path)
|
||||
) {
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
|
|
|
@ -42,7 +42,8 @@ const extractEditorSrcTask = task.define('extract-editor-src', () => {
|
|||
sourcesRoot: path.join(root, 'src'),
|
||||
entryPoints: [
|
||||
'vs/editor/editor.main',
|
||||
'vs/editor/editor.worker',
|
||||
'vs/editor/editor.worker.start',
|
||||
'vs/editor/common/services/editorSimpleWorkerMain',
|
||||
],
|
||||
inlineEntryPoints: [
|
||||
apiusages,
|
||||
|
|
|
@ -92,7 +92,7 @@ declare namespace monaco.editor {
|
|||
#includeAll(vs/editor/standalone/browser/standaloneEditor;languages.Token=>Token):
|
||||
#include(vs/editor/standalone/common/standaloneTheme): BuiltinTheme, IStandaloneThemeData, IColors
|
||||
#include(vs/editor/common/languages/supports/tokenization): ITokenThemeRule
|
||||
#include(vs/editor/standalone/browser/standaloneWebWorker): MonacoWebWorker, IWebWorkerOptions
|
||||
#include(vs/editor/standalone/browser/standaloneWebWorker): MonacoWebWorker, IInternalWebWorkerOptions
|
||||
#include(vs/editor/standalone/browser/standaloneCodeEditor): IActionDescriptor, IGlobalEditorOptions, IStandaloneEditorConstructionOptions, IStandaloneDiffEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor
|
||||
export interface ICommandHandler {
|
||||
(...args: any[]): void;
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
import { IObservable } from './vs/base/common/observable';
|
||||
|
||||
import { ServiceIdentifier } from './vs/platform/instantiation/common/instantiation';
|
||||
import { create as create1 } from './vs/base/common/worker/simpleWorker';
|
||||
import { create as create2 } from './vs/editor/common/services/editorSimpleWorker';
|
||||
import { start } from './vs/editor/editor.worker.start';
|
||||
import { SyncDescriptor0 } from './vs/platform/instantiation/common/descriptors';
|
||||
import * as editorAPI from './vs/editor/editor.api';
|
||||
|
||||
|
@ -13,8 +12,7 @@ import * as editorAPI from './vs/editor/editor.api';
|
|||
var a: any;
|
||||
var b: any;
|
||||
a = (<ServiceIdentifier<any>>b).type;
|
||||
a = create1;
|
||||
a = create2;
|
||||
a = start;
|
||||
|
||||
// injection madness
|
||||
a = (<SyncDescriptor0<any>>b).ctor;
|
||||
|
|
|
@ -959,7 +959,7 @@ export default tseslint.config(
|
|||
]
|
||||
},
|
||||
{
|
||||
'target': 'src/vs/editor/editor.worker.ts',
|
||||
'target': 'src/vs/editor/editor.worker.start.ts',
|
||||
'layer': 'worker',
|
||||
'restrictions': [
|
||||
'vs/base/~',
|
||||
|
|
|
@ -116,20 +116,22 @@ function isPromiseLike<T>(obj: any): obj is PromiseLike<T> {
|
|||
class WebWorker extends Disposable implements IWorker {
|
||||
|
||||
private readonly id: number;
|
||||
private readonly label: string;
|
||||
private worker: Promise<Worker> | null;
|
||||
|
||||
constructor(esmWorkerLocation: URI | undefined, moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {
|
||||
constructor(descriptorOrWorker: IWorkerDescriptor | Worker, id: number, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
const workerOrPromise = getWorker(esmWorkerLocation, label);
|
||||
const workerOrPromise = (
|
||||
descriptorOrWorker instanceof Worker
|
||||
? descriptorOrWorker
|
||||
: getWorker(descriptorOrWorker.esmModuleLocation, descriptorOrWorker.label || 'anonymous' + id)
|
||||
);
|
||||
if (isPromiseLike(workerOrPromise)) {
|
||||
this.worker = workerOrPromise;
|
||||
} else {
|
||||
this.worker = Promise.resolve(workerOrPromise);
|
||||
}
|
||||
this.postMessage(moduleId, []);
|
||||
this.postMessage(descriptorOrWorker instanceof Worker ? '-please-ignore-' : descriptorOrWorker.moduleId, []);
|
||||
this.worker.then((w) => {
|
||||
w.onmessage = function (ev) {
|
||||
onMessageCallback(ev.data);
|
||||
|
@ -160,7 +162,7 @@ class WebWorker extends Disposable implements IWorker {
|
|||
w.postMessage(message, transfer);
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
onUnexpectedError(new Error(`FAILED to post message to '${this.label}'-worker`, { cause: err }));
|
||||
onUnexpectedError(new Error(`FAILED to post message to worker`, { cause: err }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -187,14 +189,14 @@ class DefaultWorkerFactory implements IWorkerFactory {
|
|||
this._webWorkerFailedBeforeError = false;
|
||||
}
|
||||
|
||||
public create(desc: IWorkerDescriptor, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {
|
||||
public create(descOrWorker: IWorkerDescriptor | Worker, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {
|
||||
const workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);
|
||||
|
||||
if (this._webWorkerFailedBeforeError) {
|
||||
throw this._webWorkerFailedBeforeError;
|
||||
}
|
||||
|
||||
return new WebWorker(desc.esmModuleLocation, desc.moduleId, workerId, desc.label || 'anonymous' + workerId, onMessageCallback, (err) => {
|
||||
return new WebWorker(descOrWorker, workerId, onMessageCallback, (err) => {
|
||||
logOnceWebWorkerWarning(err);
|
||||
this._webWorkerFailedBeforeError = err;
|
||||
onErrorCallback(err);
|
||||
|
@ -203,8 +205,8 @@ class DefaultWorkerFactory implements IWorkerFactory {
|
|||
}
|
||||
|
||||
export function createWebWorker<T extends object>(moduleId: string, label: string | undefined): IWorkerClient<T>;
|
||||
export function createWebWorker<T extends object>(workerDescriptor: IWorkerDescriptor): IWorkerClient<T>;
|
||||
export function createWebWorker<T extends object>(arg0: string | IWorkerDescriptor, arg1?: string | undefined): IWorkerClient<T> {
|
||||
const workerDescriptor = (typeof arg0 === 'string' ? new WorkerDescriptor(arg0, arg1) : arg0);
|
||||
return new SimpleWorkerClient<T>(new DefaultWorkerFactory(), workerDescriptor);
|
||||
export function createWebWorker<T extends object>(workerDescriptor: IWorkerDescriptor | Worker): IWorkerClient<T>;
|
||||
export function createWebWorker<T extends object>(arg0: string | IWorkerDescriptor | Worker, arg1?: string | undefined): IWorkerClient<T> {
|
||||
const workerDescriptorOrWorker = (typeof arg0 === 'string' ? new WorkerDescriptor(arg0, arg1) : arg0);
|
||||
return new SimpleWorkerClient<T>(new DefaultWorkerFactory(), workerDescriptorOrWorker);
|
||||
}
|
||||
|
|
|
@ -231,41 +231,6 @@ export function filter(obj: obj, predicate: (key: string, value: any) => boolean
|
|||
return result;
|
||||
}
|
||||
|
||||
export function getAllPropertyNames(obj: object): string[] {
|
||||
let res: string[] = [];
|
||||
while (Object.prototype !== obj) {
|
||||
res = res.concat(Object.getOwnPropertyNames(obj));
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function getAllMethodNames(obj: object): string[] {
|
||||
const methods: string[] = [];
|
||||
for (const prop of getAllPropertyNames(obj)) {
|
||||
if (typeof (obj as any)[prop] === 'function') {
|
||||
methods.push(prop);
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
export function createProxyObject<T extends object>(methodNames: string[], invoke: (method: string, args: unknown[]) => unknown): T {
|
||||
const createProxyMethod = (method: string): () => unknown => {
|
||||
return function () {
|
||||
const args = Array.prototype.slice.call(arguments, 0);
|
||||
return invoke(method, args);
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line local/code-no-dangerous-type-assertions
|
||||
const result = {} as T;
|
||||
for (const methodName of methodNames) {
|
||||
(<any>result)[methodName] = createProxyMethod(methodName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mapValues<T extends {}, R>(obj: T, fn: (value: T[keyof T], key: string) => R): { [K in keyof T]: R } {
|
||||
const result: { [key: string]: R } = {};
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
|
|
|
@ -7,7 +7,6 @@ import { CharCode } from '../charCode.js';
|
|||
import { onUnexpectedError, transformErrorForSerialization } from '../errors.js';
|
||||
import { Emitter, Event } from '../event.js';
|
||||
import { Disposable, IDisposable } from '../lifecycle.js';
|
||||
import { AppResourcePath, FileAccess } from '../network.js';
|
||||
import { isWeb } from '../platform.js';
|
||||
import * as strings from '../strings.js';
|
||||
import { URI } from '../uri.js';
|
||||
|
@ -25,7 +24,7 @@ export interface IWorkerCallback {
|
|||
}
|
||||
|
||||
export interface IWorkerFactory {
|
||||
create(modules: IWorkerDescriptor, callback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker;
|
||||
create(modules: IWorkerDescriptor | Worker, callback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker;
|
||||
}
|
||||
|
||||
export interface IWorkerDescriptor {
|
||||
|
@ -326,15 +325,15 @@ export class SimpleWorkerClient<W extends object> extends Disposable implements
|
|||
|
||||
constructor(
|
||||
workerFactory: IWorkerFactory,
|
||||
workerDescriptor: IWorkerDescriptor,
|
||||
workerDescriptorOrWorker: IWorkerDescriptor | Worker,
|
||||
) {
|
||||
super();
|
||||
|
||||
this._worker = this._register(workerFactory.create(
|
||||
{
|
||||
workerDescriptorOrWorker instanceof Worker ? workerDescriptorOrWorker : {
|
||||
moduleId: 'vs/base/common/worker/simpleWorker',
|
||||
esmModuleLocation: workerDescriptor.esmModuleLocation,
|
||||
label: workerDescriptor.label
|
||||
esmModuleLocation: workerDescriptorOrWorker.esmModuleLocation,
|
||||
label: workerDescriptorOrWorker.label
|
||||
},
|
||||
(msg: Message) => {
|
||||
this._protocol.handleMessage(msg);
|
||||
|
@ -359,28 +358,14 @@ export class SimpleWorkerClient<W extends object> extends Disposable implements
|
|||
});
|
||||
this._protocol.setWorkerId(this._worker.getId());
|
||||
|
||||
// Gather loader configuration
|
||||
let loaderConfiguration: any = null;
|
||||
|
||||
const globalRequire: { getConfig?(): object } | undefined = (globalThis as any).require;
|
||||
if (typeof globalRequire !== 'undefined' && typeof globalRequire.getConfig === 'function') {
|
||||
// Get the configuration from the Monaco AMD Loader
|
||||
loaderConfiguration = globalRequire.getConfig();
|
||||
} else if (typeof (globalThis as any).requirejs !== 'undefined') {
|
||||
// Get the configuration from requirejs
|
||||
loaderConfiguration = (globalThis as any).requirejs.s.contexts._.config;
|
||||
}
|
||||
|
||||
// Send initialize message
|
||||
this._onModuleLoaded = this._protocol.sendMessage(DEFAULT_CHANNEL, INITIALIZE, [
|
||||
this._worker.getId(),
|
||||
JSON.parse(JSON.stringify(loaderConfiguration)),
|
||||
workerDescriptor.moduleId,
|
||||
]);
|
||||
|
||||
this.proxy = this._protocol.createProxyToRemoteChannel(DEFAULT_CHANNEL, async () => { await this._onModuleLoaded; });
|
||||
this._onModuleLoaded.catch((e) => {
|
||||
this._onError('Worker failed to load ' + workerDescriptor.moduleId, e);
|
||||
this._onError('Worker failed to load ', e);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -455,24 +440,21 @@ export interface IRequestHandler {
|
|||
[prop: string]: any;
|
||||
}
|
||||
|
||||
export interface IRequestHandlerFactory {
|
||||
(workerServer: IWorkerServer): IRequestHandler;
|
||||
export interface IRequestHandlerFactory<T extends IRequestHandler> {
|
||||
(workerServer: IWorkerServer): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Worker side
|
||||
*/
|
||||
export class SimpleWorkerServer implements IWorkerServer {
|
||||
export class SimpleWorkerServer<T extends IRequestHandler> implements IWorkerServer {
|
||||
|
||||
private _requestHandlerFactory: IRequestHandlerFactory | null;
|
||||
private _requestHandler: IRequestHandler | null;
|
||||
public readonly requestHandler: T;
|
||||
private _protocol: SimpleWorkerProtocol;
|
||||
private readonly _localChannels: Map<string, object> = new Map();
|
||||
private readonly _remoteChannels: Map<string, object> = new Map();
|
||||
|
||||
constructor(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void, requestHandlerFactory: IRequestHandlerFactory | null) {
|
||||
this._requestHandlerFactory = requestHandlerFactory;
|
||||
this._requestHandler = null;
|
||||
constructor(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void, requestHandlerFactory: IRequestHandlerFactory<T>) {
|
||||
this._protocol = new SimpleWorkerProtocol({
|
||||
sendMessage: (msg: any, transfer: ArrayBuffer[]): void => {
|
||||
postMessage(msg, transfer);
|
||||
|
@ -480,6 +462,7 @@ export class SimpleWorkerServer implements IWorkerServer {
|
|||
handleMessage: (channel: string, method: string, args: any[]): Promise<any> => this._handleMessage(channel, method, args),
|
||||
handleEvent: (channel: string, eventName: string, arg: any): Event<any> => this._handleEvent(channel, eventName, arg)
|
||||
});
|
||||
this.requestHandler = requestHandlerFactory(this);
|
||||
}
|
||||
|
||||
public onmessage(msg: any): void {
|
||||
|
@ -488,10 +471,10 @@ export class SimpleWorkerServer implements IWorkerServer {
|
|||
|
||||
private _handleMessage(channel: string, method: string, args: any[]): Promise<any> {
|
||||
if (channel === DEFAULT_CHANNEL && method === INITIALIZE) {
|
||||
return this.initialize(<number>args[0], <any>args[1], <string>args[2]);
|
||||
return this.initialize(<number>args[0]);
|
||||
}
|
||||
|
||||
const requestHandler: object | null | undefined = (channel === DEFAULT_CHANNEL ? this._requestHandler : this._localChannels.get(channel));
|
||||
const requestHandler: object | null | undefined = (channel === DEFAULT_CHANNEL ? this.requestHandler : this._localChannels.get(channel));
|
||||
if (!requestHandler) {
|
||||
return Promise.reject(new Error(`Missing channel ${channel} on worker thread`));
|
||||
}
|
||||
|
@ -507,7 +490,7 @@ export class SimpleWorkerServer implements IWorkerServer {
|
|||
}
|
||||
|
||||
private _handleEvent(channel: string, eventName: string, arg: any): Event<any> {
|
||||
const requestHandler: object | null | undefined = (channel === DEFAULT_CHANNEL ? this._requestHandler : this._localChannels.get(channel));
|
||||
const requestHandler: object | null | undefined = (channel === DEFAULT_CHANNEL ? this.requestHandler : this._localChannels.get(channel));
|
||||
if (!requestHandler) {
|
||||
throw new Error(`Missing channel ${channel} on worker thread`);
|
||||
}
|
||||
|
@ -540,50 +523,7 @@ export class SimpleWorkerServer implements IWorkerServer {
|
|||
return this._remoteChannels.get(channel) as Proxied<T>;
|
||||
}
|
||||
|
||||
private async initialize(workerId: number, loaderConfig: any, moduleId: string): Promise<void> {
|
||||
private async initialize(workerId: number): Promise<void> {
|
||||
this._protocol.setWorkerId(workerId);
|
||||
|
||||
if (this._requestHandlerFactory) {
|
||||
// static request handler
|
||||
this._requestHandler = this._requestHandlerFactory(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loaderConfig) {
|
||||
// Remove 'baseUrl', handling it is beyond scope for now
|
||||
if (typeof loaderConfig.baseUrl !== 'undefined') {
|
||||
delete loaderConfig['baseUrl'];
|
||||
}
|
||||
if (typeof loaderConfig.paths !== 'undefined') {
|
||||
if (typeof loaderConfig.paths.vs !== 'undefined') {
|
||||
delete loaderConfig.paths['vs'];
|
||||
}
|
||||
}
|
||||
if (typeof loaderConfig.trustedTypesPolicy !== 'undefined') {
|
||||
// don't use, it has been destroyed during serialize
|
||||
delete loaderConfig['trustedTypesPolicy'];
|
||||
}
|
||||
|
||||
// Since this is in a web worker, enable catching errors
|
||||
loaderConfig.catchError = true;
|
||||
(globalThis as any).require.config(loaderConfig);
|
||||
}
|
||||
|
||||
const url = FileAccess.asBrowserUri(`${moduleId}.js` as AppResourcePath).toString(true);
|
||||
return import(`${url}`).then((module: { create: IRequestHandlerFactory }) => {
|
||||
this._requestHandler = module.create(this);
|
||||
|
||||
if (!this._requestHandler) {
|
||||
throw new Error(`No RequestHandler!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the worker entry point. Must be exported and named `create`.
|
||||
* @skipMangle
|
||||
*/
|
||||
export function create(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void): SimpleWorkerServer {
|
||||
return new SimpleWorkerServer(postMessage, null);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IRequestHandlerFactory, SimpleWorkerServer } from './simpleWorker.js';
|
||||
import { IRequestHandler, IRequestHandlerFactory, SimpleWorkerServer } from './simpleWorker.js';
|
||||
|
||||
type MessageEvent = {
|
||||
data: any;
|
||||
|
@ -16,13 +16,13 @@ declare const globalThis: {
|
|||
|
||||
let initialized = false;
|
||||
|
||||
function initialize(factory: IRequestHandlerFactory) {
|
||||
function initialize<T extends IRequestHandler>(factory: IRequestHandlerFactory<T>) {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
const simpleWorker = new SimpleWorkerServer(
|
||||
const simpleWorker = new SimpleWorkerServer<T>(
|
||||
msg => globalThis.postMessage(msg),
|
||||
(workerServer) => factory(workerServer)
|
||||
);
|
||||
|
@ -32,7 +32,7 @@ function initialize(factory: IRequestHandlerFactory) {
|
|||
};
|
||||
}
|
||||
|
||||
export function bootstrapSimpleWorker(factory: IRequestHandlerFactory) {
|
||||
export function bootstrapSimpleWorker(factory: IRequestHandlerFactory<any>) {
|
||||
globalThis.onmessage = (_e: MessageEvent) => {
|
||||
// Ignore first message in this case and initialize if not yet initialized
|
||||
if (!initialized) {
|
||||
|
|
|
@ -410,7 +410,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
|
|||
private _disposed = false;
|
||||
|
||||
constructor(
|
||||
private readonly _workerDescriptor: IWorkerDescriptor,
|
||||
private readonly _workerDescriptorOrWorker: IWorkerDescriptor | Worker,
|
||||
keepIdleModels: boolean,
|
||||
@IModelService modelService: IModelService,
|
||||
) {
|
||||
|
@ -429,7 +429,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
|
|||
private _getOrCreateWorker(): IWorkerClient<EditorSimpleWorker> {
|
||||
if (!this._worker) {
|
||||
try {
|
||||
this._worker = this._register(createWebWorker<EditorSimpleWorker>(this._workerDescriptor));
|
||||
this._worker = this._register(createWebWorker<EditorSimpleWorker>(this._workerDescriptorOrWorker));
|
||||
EditorWorkerHost.setChannel(this._worker, this._createEditorWorkerHost());
|
||||
} catch (err) {
|
||||
logOnceWebWorkerWarning(err);
|
||||
|
@ -452,7 +452,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
|
|||
}
|
||||
|
||||
private _createFallbackLocalWorker(): SynchronousWorkerClient<EditorSimpleWorker> {
|
||||
return new SynchronousWorkerClient(new EditorSimpleWorker(this._createEditorWorkerHost(), null));
|
||||
return new SynchronousWorkerClient(new EditorSimpleWorker(null));
|
||||
}
|
||||
|
||||
private _createEditorWorkerHost(): EditorWorkerHost {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { stringDiff } from '../../../base/common/diff/diff.js';
|
||||
import { IDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { IRequestHandler, IWorkerServer } from '../../../base/common/worker/simpleWorker.js';
|
||||
import { IRequestHandler } from '../../../base/common/worker/simpleWorker.js';
|
||||
import { Position } from '../core/position.js';
|
||||
import { IRange, Range } from '../core/range.js';
|
||||
import { EndOfLineSequence, ITextModel } from '../model.js';
|
||||
|
@ -16,16 +16,13 @@ import { computeLinks } from '../languages/linkComputer.js';
|
|||
import { BasicInplaceReplace } from '../languages/supports/inplaceReplaceSupport.js';
|
||||
import { DiffAlgorithmName, IDiffComputationResult, ILineChange, IUnicodeHighlightsResult } from './editorWorker.js';
|
||||
import { createMonacoBaseAPI } from './editorBaseApi.js';
|
||||
import { EditorWorkerHost } from './editorWorkerHost.js';
|
||||
import { StopWatch } from '../../../base/common/stopwatch.js';
|
||||
import { UnicodeTextModelHighlighter, UnicodeHighlighterOptions } from './unicodeTextModelHighlighter.js';
|
||||
import { DiffComputer, IChange } from '../diff/legacyLinesDiffComputer.js';
|
||||
import { ILinesDiffComputer, ILinesDiffComputerOptions } from '../diff/linesDiffComputer.js';
|
||||
import { DetailedLineRangeMapping } from '../diff/rangeMapping.js';
|
||||
import { linesDiffComputers } from '../diff/linesDiffComputers.js';
|
||||
import { createProxyObject, getAllMethodNames } from '../../../base/common/objects.js';
|
||||
import { IDocumentDiffProviderOptions } from '../diff/documentDiffProvider.js';
|
||||
import { AppResourcePath, FileAccess } from '../../../base/common/network.js';
|
||||
import { BugIndicatingError } from '../../../base/common/errors.js';
|
||||
import { computeDefaultDocumentColors } from '../languages/defaultDocumentColorsComputer.js';
|
||||
import { FindSectionHeaderOptions, SectionHeader, findSectionHeaders } from './findSectionHeaders.js';
|
||||
|
@ -64,15 +61,6 @@ export interface IWordRange {
|
|||
readonly end: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IForeignModuleFactory {
|
||||
(ctx: IWorkerContext, createData: any): any;
|
||||
}
|
||||
|
||||
declare const require: any;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
@ -91,7 +79,7 @@ export class BaseEditorSimpleWorker implements IDisposable, IWorkerTextModelSync
|
|||
return this._workerTextModelSyncServer.getModel(uri);
|
||||
}
|
||||
|
||||
protected _getModels(): ICommonModel[] {
|
||||
public getModels(): ICommonModel[] {
|
||||
return this._workerTextModelSyncServer.getModels();
|
||||
}
|
||||
|
||||
|
@ -516,11 +504,8 @@ export class BaseEditorSimpleWorker implements IDisposable, IWorkerTextModelSync
|
|||
*/
|
||||
export class EditorSimpleWorker extends BaseEditorSimpleWorker {
|
||||
|
||||
private _foreignModule: any = null;
|
||||
|
||||
constructor(
|
||||
private readonly _host: EditorWorkerHost,
|
||||
private readonly _foreignModuleFactory: IForeignModuleFactory | null
|
||||
private readonly _foreignModule: any | null
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -529,40 +514,6 @@ export class EditorSimpleWorker extends BaseEditorSimpleWorker {
|
|||
return 'pong';
|
||||
}
|
||||
|
||||
// ---- BEGIN foreign module support --------------------------------------------------------------------------
|
||||
|
||||
public $loadForeignModule(moduleId: string, createData: any, foreignHostMethods: string[]): Promise<string[]> {
|
||||
const proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
|
||||
return this._host.$fhr(method, args);
|
||||
};
|
||||
|
||||
const foreignHost = createProxyObject(foreignHostMethods, proxyMethodRequest);
|
||||
|
||||
const ctx: IWorkerContext<any> = {
|
||||
host: foreignHost,
|
||||
getMirrorModels: (): IMirrorModel[] => {
|
||||
return this._getModels();
|
||||
}
|
||||
};
|
||||
|
||||
if (this._foreignModuleFactory) {
|
||||
this._foreignModule = this._foreignModuleFactory(ctx, createData);
|
||||
// static foreing module
|
||||
return Promise.resolve(getAllMethodNames(this._foreignModule));
|
||||
}
|
||||
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
|
||||
const onModuleCallback = (foreignModule: { create: IForeignModuleFactory }) => {
|
||||
this._foreignModule = foreignModule.create(ctx, createData);
|
||||
resolve(getAllMethodNames(this._foreignModule));
|
||||
};
|
||||
|
||||
const url = FileAccess.asBrowserUri(`${moduleId}.js` as AppResourcePath).toString(true);
|
||||
import(`${url}`).then(onModuleCallback).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
// foreign method request
|
||||
public $fmr(method: string, args: any[]): Promise<any> {
|
||||
if (!this._foreignModule || typeof this._foreignModule[method] !== 'function') {
|
||||
|
@ -579,15 +530,6 @@ export class EditorSimpleWorker extends BaseEditorSimpleWorker {
|
|||
// ---- END foreign module support --------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the worker entry point. Must be exported and named `create`.
|
||||
* @skipMangle
|
||||
* @internal
|
||||
*/
|
||||
export function create(workerServer: IWorkerServer): IRequestHandler {
|
||||
return new EditorSimpleWorker(EditorWorkerHost.getChannel(workerServer), null);
|
||||
}
|
||||
|
||||
// This is only available in a Web Worker
|
||||
declare function importScripts(...urls: string[]): void;
|
||||
|
||||
|
|
|
@ -3,7 +3,38 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { create } from './editorSimpleWorker.js';
|
||||
import { bootstrapSimpleEditorWorker } from './editorWorkerBootstrap.js';
|
||||
import { SimpleWorkerServer } from '../../../base/common/worker/simpleWorker.js';
|
||||
import { EditorSimpleWorker } from './editorSimpleWorker.js';
|
||||
|
||||
bootstrapSimpleEditorWorker(create);
|
||||
type MessageEvent = {
|
||||
data: any;
|
||||
};
|
||||
|
||||
declare const globalThis: {
|
||||
postMessage: (message: any) => void;
|
||||
onmessage: (event: MessageEvent) => void;
|
||||
};
|
||||
|
||||
let initialized = false;
|
||||
|
||||
function initialize() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
const simpleWorker = new SimpleWorkerServer((msg) => {
|
||||
globalThis.postMessage(msg);
|
||||
}, () => new EditorSimpleWorker(null));
|
||||
|
||||
globalThis.onmessage = (e: MessageEvent) => {
|
||||
simpleWorker.onmessage(e.data);
|
||||
};
|
||||
}
|
||||
|
||||
globalThis.onmessage = (e: MessageEvent) => {
|
||||
// Ignore first message in this case and initialize if not yet initialized
|
||||
if (!initialized) {
|
||||
initialize();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IWorkerServer, SimpleWorkerServer } from '../../../base/common/worker/simpleWorker.js';
|
||||
import { EditorSimpleWorker } from './editorSimpleWorker.js';
|
||||
import { EditorWorkerHost } from './editorWorkerHost.js';
|
||||
|
||||
type MessageEvent = {
|
||||
data: any;
|
||||
};
|
||||
|
||||
declare const globalThis: {
|
||||
postMessage: (message: any) => void;
|
||||
onmessage: (event: MessageEvent) => void;
|
||||
};
|
||||
|
||||
let initialized = false;
|
||||
|
||||
export function initialize(factory: any) {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
const simpleWorker = new SimpleWorkerServer((msg) => {
|
||||
globalThis.postMessage(msg);
|
||||
}, (workerServer: IWorkerServer) => new EditorSimpleWorker(EditorWorkerHost.getChannel(workerServer), null));
|
||||
|
||||
globalThis.onmessage = (e: MessageEvent) => {
|
||||
simpleWorker.onmessage(e.data);
|
||||
};
|
||||
}
|
||||
|
||||
globalThis.onmessage = (e: MessageEvent) => {
|
||||
// Ignore first message in this case and initialize if not yet initialized
|
||||
if (!initialized) {
|
||||
initialize(null);
|
||||
}
|
||||
};
|
||||
|
||||
type CreateFunction<C, D, R = any> = (ctx: C, data: D) => R;
|
||||
|
||||
export function bootstrapSimpleEditorWorker<C, D, R>(createFn: CreateFunction<C, D, R>) {
|
||||
globalThis.onmessage = () => {
|
||||
initialize((ctx: C, createData: D) => {
|
||||
return createFn.call(self, ctx, createData);
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SimpleWorkerServer } from '../base/common/worker/simpleWorker.js';
|
||||
import { EditorSimpleWorker, IWorkerContext } from './common/services/editorSimpleWorker.js';
|
||||
import { EditorWorkerHost } from './common/services/editorWorkerHost.js';
|
||||
|
||||
/**
|
||||
* Used by `monaco-editor` to hook up web worker rpc.
|
||||
* @skipMangle
|
||||
* @internal
|
||||
*/
|
||||
export function start<THost extends object, TClient extends object>(client: TClient): IWorkerContext<THost> {
|
||||
const simpleWorker = new SimpleWorkerServer((msg) => {
|
||||
globalThis.postMessage(msg);
|
||||
}, () => new EditorSimpleWorker(client));
|
||||
globalThis.onmessage = (e: MessageEvent) => {
|
||||
simpleWorker.onmessage(e.data);
|
||||
};
|
||||
|
||||
const editorWorkerHost = EditorWorkerHost.getChannel(simpleWorker);
|
||||
const host = new Proxy({}, {
|
||||
get(target, prop, receiver) {
|
||||
if (typeof prop !== 'string') {
|
||||
throw new Error(`Not supported`);
|
||||
}
|
||||
return (...args: any[]) => {
|
||||
return editorWorkerHost.$fhr(prop, args);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
host: host as THost,
|
||||
getMirrorModels: () => {
|
||||
return simpleWorker.requestHandler.getModels();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export * from './common/services/editorWorkerBootstrap.js';
|
|
@ -12,7 +12,7 @@ import { FontMeasurements } from '../../browser/config/fontMeasurements.js';
|
|||
import { ICodeEditor } from '../../browser/editorBrowser.js';
|
||||
import { EditorCommand, ServicesAccessor } from '../../browser/editorExtensions.js';
|
||||
import { ICodeEditorService } from '../../browser/services/codeEditorService.js';
|
||||
import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from './standaloneWebWorker.js';
|
||||
import { IInternalWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from './standaloneWebWorker.js';
|
||||
import { ApplyUpdateResult, ConfigurationChangedEvent, EditorOptions } from '../../common/config/editorOptions.js';
|
||||
import { EditorZoom } from '../../common/config/editorZoom.js';
|
||||
import { BareFontInfo, FontInfo } from '../../common/config/fontInfo.js';
|
||||
|
@ -331,7 +331,7 @@ export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextMo
|
|||
* Create a new web worker that has model syncing capabilities built in.
|
||||
* Specify an AMD module to load that will `create` an object that will be proxied.
|
||||
*/
|
||||
export function createWebWorker<T extends object>(opts: IWebWorkerOptions): MonacoWebWorker<T> {
|
||||
export function createWebWorker<T extends object>(opts: IInternalWebWorkerOptions): MonacoWebWorker<T> {
|
||||
return actualCreateWebWorker<T>(StandaloneServices.get(IModelService), opts);
|
||||
}
|
||||
|
||||
|
|
|
@ -1077,7 +1077,7 @@ class StandaloneContextMenuService extends ContextMenuService {
|
|||
}
|
||||
}
|
||||
|
||||
export const standaloneEditorWorkerDescriptor: IWorkerDescriptor = {
|
||||
const standaloneEditorWorkerDescriptor: IWorkerDescriptor = {
|
||||
moduleId: 'vs/editor/common/services/editorSimpleWorker',
|
||||
esmModuleLocation: undefined,
|
||||
label: 'editorWorkerService'
|
||||
|
|
|
@ -3,18 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getAllMethodNames } from '../../../base/common/objects.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { IWorkerDescriptor } from '../../../base/common/worker/simpleWorker.js';
|
||||
import { EditorWorkerClient } from '../../browser/services/editorWorkerService.js';
|
||||
import { IModelService } from '../../common/services/model.js';
|
||||
import { standaloneEditorWorkerDescriptor } from './standaloneServices.js';
|
||||
|
||||
/**
|
||||
* Create a new web worker that has model syncing capabilities built in.
|
||||
* Specify an AMD module to load that will `create` an object that will be proxied.
|
||||
*/
|
||||
export function createWebWorker<T extends object>(modelService: IModelService, opts: IWebWorkerOptions): MonacoWebWorker<T> {
|
||||
export function createWebWorker<T extends object>(modelService: IModelService, opts: IInternalWebWorkerOptions): MonacoWebWorker<T> {
|
||||
return new MonacoWebWorkerImpl<T>(modelService, opts);
|
||||
}
|
||||
|
||||
|
@ -37,20 +34,11 @@ export interface MonacoWebWorker<T> {
|
|||
withSyncedResources(resources: URI[]): Promise<T>;
|
||||
}
|
||||
|
||||
export interface IWebWorkerOptions {
|
||||
export interface IInternalWebWorkerOptions {
|
||||
/**
|
||||
* The AMD moduleId to load.
|
||||
* It should export a function `create` that should return the exported proxy.
|
||||
* The worker.
|
||||
*/
|
||||
moduleId: string;
|
||||
/**
|
||||
* The data to send over when calling create on the module.
|
||||
*/
|
||||
createData?: any;
|
||||
/**
|
||||
* A label to be used to identify the web worker for debugging purposes.
|
||||
*/
|
||||
label?: string;
|
||||
worker: Worker;
|
||||
/**
|
||||
* An object that can be used by the web worker to make calls back to the main thread.
|
||||
*/
|
||||
|
@ -64,22 +52,24 @@ export interface IWebWorkerOptions {
|
|||
|
||||
class MonacoWebWorkerImpl<T extends object> extends EditorWorkerClient implements MonacoWebWorker<T> {
|
||||
|
||||
private readonly _foreignModuleId: string;
|
||||
private readonly _foreignModuleHost: { [method: string]: Function } | null;
|
||||
private _foreignModuleCreateData: any | null;
|
||||
private _foreignProxy: Promise<T> | null;
|
||||
private _foreignProxy: Promise<T>;
|
||||
|
||||
constructor(modelService: IModelService, opts: IWebWorkerOptions) {
|
||||
const workerDescriptor: IWorkerDescriptor = {
|
||||
moduleId: standaloneEditorWorkerDescriptor.moduleId,
|
||||
esmModuleLocation: standaloneEditorWorkerDescriptor.esmModuleLocation,
|
||||
label: opts.label,
|
||||
};
|
||||
super(workerDescriptor, opts.keepIdleModels || false, modelService);
|
||||
this._foreignModuleId = opts.moduleId;
|
||||
this._foreignModuleCreateData = opts.createData || null;
|
||||
constructor(modelService: IModelService, opts: IInternalWebWorkerOptions) {
|
||||
super(opts.worker, opts.keepIdleModels || false, modelService);
|
||||
this._foreignModuleHost = opts.host || null;
|
||||
this._foreignProxy = null;
|
||||
this._foreignProxy = this._getProxy().then(proxy => {
|
||||
return new Proxy({}, {
|
||||
get(target, prop, receiver) {
|
||||
if (typeof prop !== 'string') {
|
||||
throw new Error(`Not supported`);
|
||||
}
|
||||
return (...args: any[]) => {
|
||||
return proxy.$fmr(prop, args);
|
||||
};
|
||||
}
|
||||
}) as T;
|
||||
});
|
||||
}
|
||||
|
||||
// foreign host request
|
||||
|
@ -95,38 +85,8 @@ class MonacoWebWorkerImpl<T extends object> extends EditorWorkerClient implement
|
|||
}
|
||||
}
|
||||
|
||||
private _getForeignProxy(): Promise<T> {
|
||||
if (!this._foreignProxy) {
|
||||
this._foreignProxy = this._getProxy().then((proxy) => {
|
||||
const foreignHostMethods = this._foreignModuleHost ? getAllMethodNames(this._foreignModuleHost) : [];
|
||||
return proxy.$loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData, foreignHostMethods).then((foreignMethods) => {
|
||||
this._foreignModuleCreateData = null;
|
||||
|
||||
const proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
|
||||
return proxy.$fmr(method, args);
|
||||
};
|
||||
|
||||
const createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise<any>): () => Promise<any> => {
|
||||
return function () {
|
||||
const args = Array.prototype.slice.call(arguments, 0);
|
||||
return proxyMethodRequest(method, args);
|
||||
};
|
||||
};
|
||||
|
||||
const foreignProxy = {} as any as T;
|
||||
for (const foreignMethod of foreignMethods) {
|
||||
(<any>foreignProxy)[foreignMethod] = createProxyMethod(foreignMethod, proxyMethodRequest);
|
||||
}
|
||||
|
||||
return foreignProxy;
|
||||
});
|
||||
});
|
||||
}
|
||||
return this._foreignProxy;
|
||||
}
|
||||
|
||||
public getProxy(): Promise<T> {
|
||||
return this._getForeignProxy();
|
||||
return this._foreignProxy;
|
||||
}
|
||||
|
||||
public withSyncedResources(resources: URI[]): Promise<T> {
|
||||
|
|
|
@ -1099,7 +1099,7 @@ declare namespace monaco.editor {
|
|||
* Create a new web worker that has model syncing capabilities built in.
|
||||
* Specify an AMD module to load that will `create` an object that will be proxied.
|
||||
*/
|
||||
export function createWebWorker<T extends object>(opts: IWebWorkerOptions): MonacoWebWorker<T>;
|
||||
export function createWebWorker<T extends object>(opts: IInternalWebWorkerOptions): MonacoWebWorker<T>;
|
||||
|
||||
/**
|
||||
* Colorize the contents of `domNode` using attribute `data-lang`.
|
||||
|
@ -1218,20 +1218,11 @@ declare namespace monaco.editor {
|
|||
withSyncedResources(resources: Uri[]): Promise<T>;
|
||||
}
|
||||
|
||||
export interface IWebWorkerOptions {
|
||||
export interface IInternalWebWorkerOptions {
|
||||
/**
|
||||
* The AMD moduleId to load.
|
||||
* It should export a function `create` that should return the exported proxy.
|
||||
* The worker.
|
||||
*/
|
||||
moduleId: string;
|
||||
/**
|
||||
* The data to send over when calling create on the module.
|
||||
*/
|
||||
createData?: any;
|
||||
/**
|
||||
* A label to be used to identify the web worker for debugging purposes.
|
||||
*/
|
||||
label?: string;
|
||||
worker: Worker;
|
||||
/**
|
||||
* An object that can be used by the web worker to make calls back to the main thread.
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as monaco from 'monaco-editor-core';
|
|||
|
||||
self.MonacoEnvironment = {
|
||||
getWorkerUrl: function (moduleId, label) {
|
||||
return './editor.worker.bundle.js';
|
||||
return './editorSimpleWorkerMain.bundle.js';
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
mode: 'production',
|
||||
entry: {
|
||||
'core': './core.js',
|
||||
'editor.worker': '../../out-monaco-editor-core/esm/vs/editor/editor.worker.js',
|
||||
'editorSimpleWorkerMain': '../../out-monaco-editor-core/esm/vs/editor/common/services/editorSimpleWorkerMain.js',
|
||||
},
|
||||
output: {
|
||||
globalObject: 'self',
|
||||
|
@ -39,7 +39,6 @@ module.exports = {
|
|||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'monaco-editor-core/esm/vs/editor/editor.worker': path.resolve(__dirname, '../../out-monaco-editor-core/esm/vs/editor/editor.worker.js'),
|
||||
'monaco-editor-core': path.resolve(__dirname, '../../out-monaco-editor-core/esm/vs/editor/editor.main.js'),
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue