提交 eefcdc9d 编写于 作者: A Alex Dima

Handle better the case when web workers are not available / misconfigured

上级 604e0d3b
# Monaco Editor Change log
## [0.5.0]
### Breaking changes
- `createWebWorker` now loads the AMD module and calls `create` and passes in as first argument a context of type `monaco.worker.IWorkerContext` and as second argument the `initData`. This breaking change was needed to allow handling the case of misconfigured web workers (running of a file protocol or a cross-domain case)
- the `CodeActionProvider.provideCodeActions` now gets passed in a `CodeActionContext` that contains the markers at the relevant range.
\ No newline at end of file
...@@ -165,9 +165,21 @@ export class SimpleWorkerClient<T> extends Disposable { ...@@ -165,9 +165,21 @@ export class SimpleWorkerClient<T> extends Disposable {
constructor(workerFactory:IWorkerFactory, moduleId:string) { constructor(workerFactory:IWorkerFactory, moduleId:string) {
super(); super();
this._worker = this._register(workerFactory.create('vs/base/common/worker/simpleWorker', (msg:string) => {
this._protocol.handleMessage(msg); let lazyProxyFulfill : (v:T)=>void = null;
})); let lazyProxyReject: (err:any)=>void = null;
this._worker = this._register(workerFactory.create(
'vs/base/common/worker/simpleWorker',
(msg:string) => {
this._protocol.handleMessage(msg);
},
(err:any) => {
// in Firefox, web workers fail lazily :(
// we will reject the proxy
lazyProxyReject(err);
}
));
this._protocol = new SimpleWorkerProtocol({ this._protocol = new SimpleWorkerProtocol({
sendMessage: (msg:string): void => { sendMessage: (msg:string): void => {
...@@ -191,9 +203,6 @@ export class SimpleWorkerClient<T> extends Disposable { ...@@ -191,9 +203,6 @@ export class SimpleWorkerClient<T> extends Disposable {
loaderConfiguration = (<any>window).requirejs.s.contexts._.config; loaderConfiguration = (<any>window).requirejs.s.contexts._.config;
} }
let lazyProxyFulfill : (v:T)=>void = null;
let lazyProxyReject: (err:any)=>void = null;
this._lazyProxy = new TPromise((c, e, p) => { this._lazyProxy = new TPromise((c, e, p) => {
lazyProxyFulfill = c; lazyProxyFulfill = c;
lazyProxyReject = e; lazyProxyReject = e;
......
...@@ -17,12 +17,21 @@ export interface IWorker { ...@@ -17,12 +17,21 @@ export interface IWorker {
dispose():void; dispose():void;
} }
let webWorkerWarningLogged = false;
export function logOnceWebWorkerWarning(err:any): void {
if (!webWorkerWarningLogged) {
webWorkerWarningLogged = true;
console.warn('Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq');
}
console.warn(err.message);
}
export interface IWorkerCallback { export interface IWorkerCallback {
(message:string):void; (message:string):void;
} }
export interface IWorkerFactory { export interface IWorkerFactory {
create(moduleId:string, callback:IWorkerCallback, onCrashCallback?:()=>void):IWorker; create(moduleId:string, callback:IWorkerCallback, onErrorCallback:(err:any)=>void):IWorker;
} }
interface IActiveRequest { interface IActiveRequest {
...@@ -59,7 +68,15 @@ export class WorkerClient { ...@@ -59,7 +68,15 @@ export class WorkerClient {
this._waitingForWorkerReply = false; this._waitingForWorkerReply = false;
this._lastTimerEvent = null; this._lastTimerEvent = null;
this._worker = workerFactory.create('vs/base/common/worker/workerServer', (msg) => this._onSerializedMessage(msg)); this._worker = workerFactory.create(
'vs/base/common/worker/workerServer',
(msg) => this._onSerializedMessage(msg),
(err) => {
// reject the onModuleLoaded promise, this signals that things are bad
let promiseEntry:IActiveRequest = this._promises[1];
delete this._promises[1];
promiseEntry.error(err);
});
let loaderConfiguration:any = null; let loaderConfiguration:any = null;
...@@ -80,7 +97,6 @@ export class WorkerClient { ...@@ -80,7 +97,6 @@ export class WorkerClient {
loaderConfiguration: loaderConfiguration, loaderConfiguration: loaderConfiguration,
GlobalEnvironment: GlobalEnvironment GlobalEnvironment: GlobalEnvironment
}); });
this.onModuleLoaded.then(null, (e) => this._onError('Worker failed to load ' + moduleId, e));
this._remoteCom = new workerProtocol.RemoteCom(this); this._remoteCom = new workerProtocol.RemoteCom(this);
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import * as flags from 'vs/base/common/flags'; import * as flags from 'vs/base/common/flags';
import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IWorker, IWorkerCallback, IWorkerFactory} from 'vs/base/common/worker/workerClient'; import {logOnceWebWorkerWarning, IWorker, IWorkerCallback, IWorkerFactory} from 'vs/base/common/worker/workerClient';
import * as dom from 'vs/base/browser/dom'; import * as dom from 'vs/base/browser/dom';
function defaultGetWorkerUrl(workerId:string, label:string): string { function defaultGetWorkerUrl(workerId:string, label:string): string {
...@@ -24,13 +24,16 @@ class WebWorker implements IWorker { ...@@ -24,13 +24,16 @@ class WebWorker implements IWorker {
private id:number; private id:number;
private worker:Worker; private worker:Worker;
constructor(moduleId:string, id:number, label:string, onMessageCallback:IWorkerCallback) { constructor(moduleId:string, id:number, label:string, onMessageCallback:IWorkerCallback, onErrorCallback:(err:any)=>void) {
this.id = id; this.id = id;
this.worker = new Worker(getWorkerUrl('workerMain.js', label)); this.worker = new Worker(getWorkerUrl('workerMain.js', label));
this.postMessage(moduleId); this.postMessage(moduleId);
this.worker.onmessage = function (ev:any) { this.worker.onmessage = function (ev:any) {
onMessageCallback(ev.data); onMessageCallback(ev.data);
}; };
if (typeof this.worker.addEventListener === 'function') {
this.worker.addEventListener('error', onErrorCallback);
}
} }
public getId(): number { public getId(): number {
...@@ -125,11 +128,41 @@ export class DefaultWorkerFactory implements IWorkerFactory { ...@@ -125,11 +128,41 @@ export class DefaultWorkerFactory implements IWorkerFactory {
private static LAST_WORKER_ID = 0; private static LAST_WORKER_ID = 0;
public create(moduleId:string, onMessageCallback:IWorkerCallback):IWorker { private _fallbackToIframe:boolean;
var workerId = (++DefaultWorkerFactory.LAST_WORKER_ID); private _webWorkerFailedBeforeError:any;
if (typeof WebWorker !== 'undefined') {
return new WebWorker(moduleId, workerId, 'service' + workerId, onMessageCallback); constructor(fallbackToIframe:boolean) {
this._fallbackToIframe = fallbackToIframe;
this._webWorkerFailedBeforeError = false;
}
public create(moduleId:string, onMessageCallback:IWorkerCallback, onErrorCallback:(err:any)=>void):IWorker {
let workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);
if (this._fallbackToIframe) {
if (this._webWorkerFailedBeforeError) {
// Avoid always trying to create web workers if they would just fail...
return new FrameWorker(moduleId, workerId, onMessageCallback);
}
try {
return new WebWorker(moduleId, workerId, 'service' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
onErrorCallback(err);
});
} catch(err) {
logOnceWebWorkerWarning(err);
return new FrameWorker(moduleId, workerId, onMessageCallback);
}
} }
return new FrameWorker(moduleId, workerId, onMessageCallback);
if (this._webWorkerFailedBeforeError) {
throw this._webWorkerFailedBeforeError;
}
return new WebWorker(moduleId, workerId, 'service' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
onErrorCallback(err);
});
} }
} }
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle';
import {IRequestHandler} from 'vs/base/common/worker/simpleWorker'; import {IRequestHandler} from 'vs/base/common/worker/simpleWorker';
import {Range} from 'vs/editor/common/core/range'; import {Range} from 'vs/editor/common/core/range';
import {fuzzyContiguousFilter} from 'vs/base/common/filters'; import {fuzzyContiguousFilter} from 'vs/base/common/filters';
...@@ -23,13 +24,37 @@ import {createMonacoBaseAPI} from 'vs/editor/common/standalone/standaloneBase'; ...@@ -23,13 +24,37 @@ import {createMonacoBaseAPI} from 'vs/editor/common/standalone/standaloneBase';
export interface IMirrorModel { export interface IMirrorModel {
uri: URI; uri: URI;
version: number; version: number;
getText(): string; getValue(): string;
}
export interface IWorkerContext {
/**
* Get all available mirror models in this worker.
*/
getMirrorModels(): IMirrorModel[];
}
/**
* @internal
*/
export interface ICommonModel {
uri: URI;
version: number;
getValue(): string;
getLinesContent(): string[];
getLineCount(): number;
getLineContent(lineNumber:number): string;
getWordUntilPosition(position: editorCommon.IPosition, wordDefinition:RegExp): editorCommon.IWordAtPosition;
getAllUniqueWords(wordDefinition:RegExp, skipWordOnce?:string) : string[];
getValueInRange(range:editorCommon.IRange): string;
getWordAtPosition(position:editorCommon.IPosition, wordDefinition:RegExp): Range;
} }
/** /**
* @internal * @internal
*/ */
export class MirrorModel extends MirrorModel2 { export class MirrorModel extends MirrorModel2 implements ICommonModel {
public get uri(): URI { public get uri(): URI {
return this._uri; return this._uri;
...@@ -39,6 +64,10 @@ export class MirrorModel extends MirrorModel2 { ...@@ -39,6 +64,10 @@ export class MirrorModel extends MirrorModel2 {
return this._versionId; return this._versionId;
} }
public getValue(): string {
return this.getText();
}
public getLinesContent(): string[] { public getLinesContent(): string[] {
return this._lines.slice(0); return this._lines.slice(0);
} }
...@@ -146,47 +175,21 @@ export class MirrorModel extends MirrorModel2 { ...@@ -146,47 +175,21 @@ export class MirrorModel extends MirrorModel2 {
/** /**
* @internal * @internal
*/ */
export class EditorSimpleWorkerImpl implements IRequestHandler { export abstract class BaseEditorSimpleWorker {
_requestHandlerTrait: any;
private _models:{[uri:string]:MirrorModel;};
private _foreignModule: any; private _foreignModule: any;
constructor() { constructor() {
this._models = Object.create(null);
this._foreignModule = null; this._foreignModule = null;
} }
public getModels(): MirrorModel[] { protected abstract _getModel(uri:string): ICommonModel;
let all: MirrorModel[] = []; protected abstract _getModels(): ICommonModel[];
Object.keys(this._models).forEach((key) => all.push(this._models[key]));
return all;
}
public acceptNewModel(data:IRawModelData): void {
this._models[data.url] = new MirrorModel(URI.parse(data.url), data.value.lines, data.value.EOL, data.versionId);
}
public acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void {
if (!this._models[strURL]) {
return;
}
let model = this._models[strURL];
model.onEvents(events);
}
public acceptRemovedModel(strURL: string): void {
if (!this._models[strURL]) {
return;
}
delete this._models[strURL];
}
// ---- BEGIN diff -------------------------------------------------------------------------- // ---- BEGIN diff --------------------------------------------------------------------------
public computeDiff(originalUrl:string, modifiedUrl:string, ignoreTrimWhitespace:boolean): TPromise<editorCommon.ILineChange[]> { public computeDiff(originalUrl:string, modifiedUrl:string, ignoreTrimWhitespace:boolean): TPromise<editorCommon.ILineChange[]> {
let original = this._models[originalUrl]; let original = this._getModel(originalUrl);
let modified = this._models[modifiedUrl]; let modified = this._getModel(modifiedUrl);
if (!original || !modified) { if (!original || !modified) {
return null; return null;
} }
...@@ -202,8 +205,8 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -202,8 +205,8 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
} }
public computeDirtyDiff(originalUrl:string, modifiedUrl:string, ignoreTrimWhitespace:boolean):TPromise<editorCommon.IChange[]> { public computeDirtyDiff(originalUrl:string, modifiedUrl:string, ignoreTrimWhitespace:boolean):TPromise<editorCommon.IChange[]> {
let original = this._models[originalUrl]; let original = this._getModel(originalUrl);
let modified = this._models[modifiedUrl]; let modified = this._getModel(modifiedUrl);
if (!original || !modified) { if (!original || !modified) {
return null; return null;
} }
...@@ -221,7 +224,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -221,7 +224,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
// ---- END diff -------------------------------------------------------------------------- // ---- END diff --------------------------------------------------------------------------
public computeLinks(modelUrl:string):TPromise<ILink[]> { public computeLinks(modelUrl:string):TPromise<ILink[]> {
let model = this._models[modelUrl]; let model = this._getModel(modelUrl);
if (!model) { if (!model) {
return null; return null;
} }
...@@ -232,7 +235,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -232,7 +235,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
// ---- BEGIN suggest -------------------------------------------------------------------------- // ---- BEGIN suggest --------------------------------------------------------------------------
public textualSuggest(modelUrl:string, position: editorCommon.IPosition, wordDef:string, wordDefFlags:string): TPromise<ISuggestResult[]> { public textualSuggest(modelUrl:string, position: editorCommon.IPosition, wordDef:string, wordDefFlags:string): TPromise<ISuggestResult[]> {
let model = this._models[modelUrl]; let model = this._getModel(modelUrl);
if (!model) { if (!model) {
return null; return null;
} }
...@@ -240,7 +243,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -240,7 +243,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
return TPromise.as(this._suggestFiltered(model, position, new RegExp(wordDef, wordDefFlags))); return TPromise.as(this._suggestFiltered(model, position, new RegExp(wordDef, wordDefFlags)));
} }
private _suggestFiltered(model:MirrorModel, position: editorCommon.IPosition, wordDefRegExp: RegExp): ISuggestResult[] { private _suggestFiltered(model:ICommonModel, position: editorCommon.IPosition, wordDefRegExp: RegExp): ISuggestResult[] {
let value = this._suggestUnfiltered(model, position, wordDefRegExp); let value = this._suggestUnfiltered(model, position, wordDefRegExp);
// filter suggestions // filter suggestions
...@@ -251,7 +254,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -251,7 +254,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
}]; }];
} }
private _suggestUnfiltered(model:MirrorModel, position:editorCommon.IPosition, wordDefRegExp: RegExp): ISuggestResult { private _suggestUnfiltered(model:ICommonModel, position:editorCommon.IPosition, wordDefRegExp: RegExp): ISuggestResult {
let currentWord = model.getWordUntilPosition(position, wordDefRegExp).word; let currentWord = model.getWordUntilPosition(position, wordDefRegExp).word;
let allWords = model.getAllUniqueWords(wordDefRegExp, currentWord); let allWords = model.getAllUniqueWords(wordDefRegExp, currentWord);
...@@ -275,7 +278,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -275,7 +278,7 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
// ---- END suggest -------------------------------------------------------------------------- // ---- END suggest --------------------------------------------------------------------------
public navigateValueSet(modelUrl:string, range:editorCommon.IRange, up:boolean, wordDef:string, wordDefFlags:string): TPromise<IInplaceReplaceSupportResult> { public navigateValueSet(modelUrl:string, range:editorCommon.IRange, up:boolean, wordDef:string, wordDefFlags:string): TPromise<IInplaceReplaceSupportResult> {
let model = this._models[modelUrl]; let model = this._getModel(modelUrl);
if (!model) { if (!model) {
return null; return null;
} }
...@@ -304,7 +307,12 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -304,7 +307,12 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
return new TPromise<any>((c, e) => { return new TPromise<any>((c, e) => {
// Use the global require to be sure to get the global config // Use the global require to be sure to get the global config
(<any>self).require([moduleId], (foreignModule) => { (<any>self).require([moduleId], (foreignModule) => {
this._foreignModule = foreignModule.create(createData); let ctx: IWorkerContext = {
getMirrorModels: ():IMirrorModel[] => {
return this._getModels();
}
};
this._foreignModule = foreignModule.create(ctx, createData);
let methods: string[] = []; let methods: string[] = [];
for (let prop in this._foreignModule) { for (let prop in this._foreignModule) {
...@@ -335,13 +343,51 @@ export class EditorSimpleWorkerImpl implements IRequestHandler { ...@@ -335,13 +343,51 @@ export class EditorSimpleWorkerImpl implements IRequestHandler {
// ---- END foreign module support -------------------------------------------------------------------------- // ---- END foreign module support --------------------------------------------------------------------------
} }
const instance = new EditorSimpleWorkerImpl();
/** /**
* Get all available mirror models in this worker. * @internal
*/ */
export function getMirrorModels(): IMirrorModel[] { export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IRequestHandler, IDisposable {
return instance.getModels(); _requestHandlerTrait: any;
private _models:{[uri:string]:MirrorModel;};
constructor() {
super();
this._models = Object.create(null);
}
public dispose(): void {
this._models = Object.create(null);
}
protected _getModel(uri:string): ICommonModel {
return this._models[uri];
}
protected _getModels(): ICommonModel[] {
let all: MirrorModel[] = [];
Object.keys(this._models).forEach((key) => all.push(this._models[key]));
return all;
}
public acceptNewModel(data:IRawModelData): void {
this._models[data.url] = new MirrorModel(URI.parse(data.url), data.value.lines, data.value.EOL, data.versionId);
}
public acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void {
if (!this._models[strURL]) {
return;
}
let model = this._models[strURL];
model.onEvents(events);
}
public acceptRemovedModel(strURL: string): void {
if (!this._models[strURL]) {
return;
}
delete this._models[strURL];
}
} }
/** /**
...@@ -349,15 +395,11 @@ export function getMirrorModels(): IMirrorModel[] { ...@@ -349,15 +395,11 @@ export function getMirrorModels(): IMirrorModel[] {
* @internal * @internal
*/ */
export function create(): IRequestHandler { export function create(): IRequestHandler {
return instance; return new EditorSimpleWorkerImpl();
}
function createMonacoWorkerAPI(): typeof monaco.worker {
return {
getMirrorModels: getMirrorModels
};
} }
var global:any = self; var global:any = self;
global.monaco = createMonacoBaseAPI(); let isWebWorker = (typeof global.importScripts === 'function');
global.monaco.worker = createMonacoWorkerAPI(); if (isWebWorker) {
global.monaco = createMonacoBaseAPI();
}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {IntervalTimer} from 'vs/base/common/async'; import {IntervalTimer, ShallowCancelThenPromise} from 'vs/base/common/async';
import {Disposable, IDisposable, dispose} from 'vs/base/common/lifecycle'; import {Disposable, IDisposable, dispose} from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
...@@ -16,6 +16,7 @@ import {IInplaceReplaceSupportResult, ILink, ISuggestResult} from 'vs/editor/com ...@@ -16,6 +16,7 @@ import {IInplaceReplaceSupportResult, ILink, ISuggestResult} from 'vs/editor/com
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
import {IModelService} from 'vs/editor/common/services/modelService'; import {IModelService} from 'vs/editor/common/services/modelService';
import {EditorSimpleWorkerImpl} from 'vs/editor/common/services/editorSimpleWorker'; import {EditorSimpleWorkerImpl} from 'vs/editor/common/services/editorSimpleWorker';
import {logOnceWebWorkerWarning} from 'vs/base/common/worker/workerClient';
/** /**
* Stop syncing a model to the worker if it was not needed for 1 min. * Stop syncing a model to the worker if it was not needed for 1 min.
...@@ -211,31 +212,67 @@ class EditorModelManager extends Disposable { ...@@ -211,31 +212,67 @@ class EditorModelManager extends Disposable {
} }
} }
interface IWorkerClient<T> {
getProxyObject(): TPromise<T>;
dispose(): void;
}
class SynchronousWorkerClient<T extends IDisposable> implements IWorkerClient<T> {
private _instance: T;
private _proxyObj: TPromise<T>;
constructor(instance:T) {
this._instance = instance;
this._proxyObj = TPromise.as(this._instance);
}
public dispose(): void {
this._instance.dispose();
this._instance = null;
this._proxyObj = null;
}
public getProxyObject(): TPromise<T> {
return new ShallowCancelThenPromise(this._proxyObj);
}
}
export class EditorWorkerClient extends Disposable { export class EditorWorkerClient extends Disposable {
private _modelService: IModelService; private _modelService: IModelService;
private _worker: SimpleWorkerClient<EditorSimpleWorkerImpl>; private _worker: IWorkerClient<EditorSimpleWorkerImpl>;
private _workerFactory: DefaultWorkerFactory;
private _modelManager: EditorModelManager; private _modelManager: EditorModelManager;
constructor(modelService: IModelService) { constructor(modelService: IModelService) {
super(); super();
this._modelService = modelService; this._modelService = modelService;
this._workerFactory = new DefaultWorkerFactory(/*do not use iframe*/false);
this._worker = null; this._worker = null;
this._modelManager = null; this._modelManager = null;
} }
private _getOrCreateWorker(): SimpleWorkerClient<EditorSimpleWorkerImpl> { private _getOrCreateWorker(): IWorkerClient<EditorSimpleWorkerImpl> {
if (!this._worker) { if (!this._worker) {
this._worker = this._register(new SimpleWorkerClient<EditorSimpleWorkerImpl>( try {
new DefaultWorkerFactory(), this._worker = this._register(new SimpleWorkerClient<EditorSimpleWorkerImpl>(
'vs/editor/common/services/editorSimpleWorker' this._workerFactory,
)); 'vs/editor/common/services/editorSimpleWorker'
));
} catch (err) {
logOnceWebWorkerWarning(err);
this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl());
}
} }
return this._worker; return this._worker;
} }
protected _getProxy(): TPromise<EditorSimpleWorkerImpl> { protected _getProxy(): TPromise<EditorSimpleWorkerImpl> {
return this._getOrCreateWorker().getProxyObject(); return this._getOrCreateWorker().getProxyObject().then(null, (err) => {
logOnceWebWorkerWarning(err);
this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl());
return this._getOrCreateWorker().getProxyObject();
});
} }
private _getOrCreateModelManager(proxy: EditorSimpleWorkerImpl): EditorModelManager { private _getOrCreateModelManager(proxy: EditorSimpleWorkerImpl): EditorModelManager {
......
...@@ -17,7 +17,6 @@ import URI from 'vs/base/common/uri'; ...@@ -17,7 +17,6 @@ import URI from 'vs/base/common/uri';
export function createMonacoBaseAPI(): typeof monaco { export function createMonacoBaseAPI(): typeof monaco {
return { return {
editor: undefined, editor: undefined,
worker: undefined,
languages: undefined, languages: undefined,
CancellationTokenSource: CancellationTokenSource, CancellationTokenSource: CancellationTokenSource,
Emitter: Emitter, Emitter: Emitter,
......
...@@ -4725,12 +4725,14 @@ declare module monaco.worker { ...@@ -4725,12 +4725,14 @@ declare module monaco.worker {
export interface IMirrorModel { export interface IMirrorModel {
uri: Uri; uri: Uri;
version: number; version: number;
getText(): string; getValue(): string;
} }
/** export interface IWorkerContext {
* Get all available mirror models in this worker. /**
*/ * Get all available mirror models in this worker.
export function getMirrorModels(): IMirrorModel[]; */
getMirrorModels(): IMirrorModel[];
}
} }
\ No newline at end of file
...@@ -47,7 +47,7 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi ...@@ -47,7 +47,7 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi
this._contextService = contextService; this._contextService = contextService;
this._workerModuleId = workerModuleId; this._workerModuleId = workerModuleId;
this._defaultWorkerCount = defaultWorkerCount; this._defaultWorkerCount = defaultWorkerCount;
this._workerFactory = new DefaultWorkerFactory(); this._workerFactory = new DefaultWorkerFactory(true);
if (!this.isInMainThread) { if (!this.isInMainThread) {
throw new Error('Incorrect Service usage: this service must be used only in the main thread'); throw new Error('Incorrect Service usage: this service must be used only in the main thread');
...@@ -105,15 +105,11 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi ...@@ -105,15 +105,11 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi
}); });
} }
private _createWorker(): void {
this._workerPool.push(this._doCreateWorker());
}
private _shortName(major: string, minor: string): string { private _shortName(major: string, minor: string): string {
return major.substring(major.length - 14) + '.' + minor.substr(0, 14); return major.substring(major.length - 14) + '.' + minor.substr(0, 14);
} }
private _doCreateWorker(): Worker.WorkerClient { private _createWorker(isRetry:boolean = false): void {
let worker = new Worker.WorkerClient( let worker = new Worker.WorkerClient(
this._workerFactory, this._workerFactory,
this._workerModuleId, this._workerModuleId,
...@@ -131,9 +127,22 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi ...@@ -131,9 +127,22 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi
configuration: this._contextService.getConfiguration(), configuration: this._contextService.getConfiguration(),
options: this._contextService.getOptions() options: this._contextService.getOptions()
} }
}).then(null, (err) => {
for (var i = 0; i < this._workerPool.length; i++) {
if (this._workerPool[i] === worker) {
this._workerPool.splice(i, 1);
break;
}
}
worker.dispose();
if (isRetry) {
console.warn('Creating the web worker already failed twice. Giving up!');
} else {
this._createWorker(true);
}
}); });
return worker; this._workerPool.push(worker);
} }
private _getWorkerIndex(obj: IThreadSynchronizableObject, affinity: ThreadAffinity): number { private _getWorkerIndex(obj: IThreadSynchronizableObject, affinity: ThreadAffinity): number {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册