Merge from vscode 1eb87b0e9ce9886afeaecec22b31abd0d9b7939f (#7282)

* Merge from vscode 1eb87b0e9ce9886afeaecec22b31abd0d9b7939f

* fix various icon issues

* fix preview features
This commit is contained in:
Anthony Dresser
2019-09-19 21:50:52 -07:00
committed by GitHub
parent 9d3d64eef3
commit db498db0a8
459 changed files with 10195 additions and 7528 deletions

View File

@@ -8,6 +8,9 @@ import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
import { VSBuffer } from 'vs/base/common/buffer';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import * as dom from 'vs/base/browser/dom';
import { RunOnceScheduler } from 'vs/base/common/async';
import { RemoteAuthorityResolverError, RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
export interface IWebSocketFactory {
create(url: string): IWebSocket;
@@ -23,27 +26,34 @@ export interface IWebSocket {
close(): void;
}
class BrowserWebSocket implements IWebSocket {
class BrowserWebSocket extends Disposable implements IWebSocket {
private readonly _onData = new Emitter<ArrayBuffer>();
public readonly onData = this._onData.event;
public readonly onOpen: Event<void>;
public readonly onClose: Event<void>;
public readonly onError: Event<any>;
private readonly _onClose = this._register(new Emitter<void>());
public readonly onClose = this._onClose.event;
private readonly _onError = this._register(new Emitter<any>());
public readonly onError = this._onError.event;
private readonly _socket: WebSocket;
private readonly _fileReader: FileReader;
private readonly _queue: Blob[];
private _isReading: boolean;
private _isClosed: boolean;
private readonly _socketMessageListener: (ev: MessageEvent) => void;
constructor(socket: WebSocket) {
super();
this._socket = socket;
this._fileReader = new FileReader();
this._queue = [];
this._isReading = false;
this._isClosed = false;
this._fileReader.onload = (event) => {
this._isReading = false;
@@ -71,17 +81,79 @@ class BrowserWebSocket implements IWebSocket {
this._socket.addEventListener('message', this._socketMessageListener);
this.onOpen = Event.fromDOMEventEmitter(this._socket, 'open');
this.onClose = Event.fromDOMEventEmitter(this._socket, 'close');
this.onError = Event.fromDOMEventEmitter(this._socket, 'error');
// WebSockets emit error events that do not contain any real information
// Our only chance of getting to the root cause of an error is to
// listen to the close event which gives out some real information:
// - https://www.w3.org/TR/websockets/#closeevent
// - https://tools.ietf.org/html/rfc6455#section-11.7
//
// But the error event is emitted before the close event, so we therefore
// delay the error event processing in the hope of receiving a close event
// with more information
let pendingErrorEvent: any | null = null;
const sendPendingErrorNow = () => {
const err = pendingErrorEvent;
pendingErrorEvent = null;
this._onError.fire(err);
};
const errorRunner = this._register(new RunOnceScheduler(sendPendingErrorNow, 0));
const sendErrorSoon = (err: any) => {
errorRunner.cancel();
pendingErrorEvent = err;
errorRunner.schedule();
};
const sendErrorNow = (err: any) => {
errorRunner.cancel();
pendingErrorEvent = err;
sendPendingErrorNow();
};
this._register(dom.addDisposableListener(this._socket, 'close', (e: CloseEvent) => {
this._isClosed = true;
if (pendingErrorEvent) {
if (!window.navigator.onLine) {
// The browser is offline => this is a temporary error which might resolve itself
sendErrorNow(new RemoteAuthorityResolverError('Browser is offline', RemoteAuthorityResolverErrorCode.TemporarilyNotAvailable, e));
} else {
// An error event is pending
// The browser appears to be online...
if (!e.wasClean) {
// Let's be optimistic and hope that perhaps the server could not be reached or something
sendErrorNow(new RemoteAuthorityResolverError(e.reason || `WebSocket close with status code ${e.code}`, RemoteAuthorityResolverErrorCode.TemporarilyNotAvailable, e));
} else {
// this was a clean close => send existing error
errorRunner.cancel();
sendPendingErrorNow();
}
}
}
this._onClose.fire();
}));
this._register(dom.addDisposableListener(this._socket, 'error', sendErrorSoon));
}
send(data: ArrayBuffer | ArrayBufferView): void {
if (this._isClosed) {
// Refuse to write data to closed WebSocket...
return;
}
this._socket.send(data);
}
close(): void {
this._isClosed = true;
this._socket.close();
this._socket.removeEventListener('message', this._socketMessageListener);
this.dispose();
}
}