diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 0eb9f38f93f..ae67693841b 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -77,12 +77,6 @@ namespace Utils { return Buffer ? Buffer.byteLength(s, encoding) : s.length; } - export function compress(s: string): any { - return Buffer ? new Buffer(s, "utf8") : { data: s, length: s.length }; - } - - export const maxUncompressedMessageSize = Number.MAX_VALUE; - export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { const environment = getExecutionEnvironment(); switch (environment) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 5710d5e862c..5da61fd542a 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -696,10 +696,8 @@ namespace Harness.LanguageService { const server = new ts.server.Session(serverHost, { isCancellationRequested: () => false }, /*useOneInferredProject*/ false, - /*typingsInstaller*/ undefined, + /*typingsInstaller*/ undefined, Utils.byteLength, - Utils.maxUncompressedMessageSize, - Utils.compress, process.hrtime, serverHost); // Fake the connection between the client and the server diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 5dfc3738661..0d1fb3681e0 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -44,7 +44,7 @@ namespace ts.server { let lastSent: protocol.Message; beforeEach(() => { - session = new Session(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, Utils.maxUncompressedMessageSize, Utils.compress, process.hrtime, mockLogger); + session = new Session(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger); session.send = (msg: protocol.Message) => { lastSent = msg; }; @@ -182,7 +182,7 @@ namespace ts.server { session.send = Session.prototype.send; assert(session.send); - expect(session.send(msg, /*canCompressResponse*/ false)).to.not.exist; + expect(session.send(msg)).to.not.exist; expect(lastWrittenToHost).to.equal(resultMsg); }); }); @@ -250,7 +250,7 @@ namespace ts.server { }; const command = "test"; - session.output(body, command, /*canCompressResponse*/ false); + session.output(body, command); expect(lastSent).to.deep.equal({ seq: 0, @@ -269,7 +269,7 @@ namespace ts.server { lastSent: protocol.Message; customHandler = "testhandler"; constructor() { - super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, Utils.maxUncompressedMessageSize, Utils.compress, process.hrtime, mockLogger); + super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger); this.addProtocolHandler(this.customHandler, () => { return { response: undefined, responseRequired: true }; }); @@ -288,7 +288,7 @@ namespace ts.server { }; const command = "test"; - session.output(body, command, /*canCompressResponse*/ false); + session.output(body, command); expect(session.lastSent).to.deep.equal({ seq: 0, @@ -327,7 +327,7 @@ namespace ts.server { class InProcSession extends Session { private queue: protocol.Request[] = []; constructor(private client: InProcClient) { - super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, Utils.maxUncompressedMessageSize, Utils.compress, process.hrtime, mockLogger); + super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger); this.addProtocolHandler("echo", (req: protocol.Request) => ({ response: req.arguments, responseRequired: true @@ -348,11 +348,11 @@ namespace ts.server { ({ response } = this.executeCommand(msg)); } catch (e) { - this.output(undefined, msg.command, /*canCompressResponse*/ false, msg.seq, e.toString()); + this.output(undefined, msg.command, msg.seq, e.toString()); return; } if (response) { - this.output(response, msg.command, /*canCompressResponse*/ false, msg.seq); + this.output(response, msg.command, msg.seq); } } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 2a08e4c3bbd..ec3d219c5b5 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -30,8 +30,6 @@ declare namespace ts.server.protocol { * Object containing arguments for the command */ arguments?: any; - - canCompressResponse?: boolean; } /** diff --git a/src/server/server.ts b/src/server/server.ts index 1ae385f7b8a..dc614fba1f7 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -5,10 +5,6 @@ namespace ts.server { - const zlib: { - gzipSync(buf: Buffer): Buffer - } = require("zlib"); - const net: { connect(options: { port: number }, onConnect?: () => void): NodeSocket } = require("net"); @@ -86,13 +82,6 @@ namespace ts.server { terminal: false, }); - function compress(s: string): CompressedData { - const data = zlib.gzipSync(new Buffer(s, "utf8")); - return { data, length: data.length, compressionKind: "gzip" }; - } - - const maxUncompressedMessageSize = 84000; - class Logger implements ts.server.Logger { private fd = -1; private seq = 0; @@ -178,7 +167,7 @@ namespace ts.server { private socket: NodeSocket; private projectService: ProjectService; - constructor(private readonly logger: server.Logger, private readonly eventPort: number) { + constructor(private readonly logger: server.Logger, private readonly eventPort: number, private newLine: string) { if (eventPort) { const s = net.connect({ port: eventPort }, () => { this.socket = s; @@ -221,14 +210,14 @@ namespace ts.server { } this.projectService.updateTypingsForProject(response); if (response.kind == "set" && this.socket) { - this.socket.write(JSON.stringify({ kind: "updateTypings", message: response }) + "\r\n", "utf8"); + this.socket.write(formatMessage({ seq: 0, type: "event", message: response }, this.logger, Buffer.byteLength, this.newLine), "utf8"); } } } class IOSession extends Session { constructor(host: ServerHost, cancellationToken: HostCancellationToken, eventPort: number, useSingleInferredProject: boolean, logger: server.Logger) { - super(host, cancellationToken, useSingleInferredProject, new NodeTypingsInstaller(logger, eventPort), Buffer.byteLength, maxUncompressedMessageSize, compress, process.hrtime, logger); + super(host, cancellationToken, useSingleInferredProject, new NodeTypingsInstaller(logger, eventPort, host.newLine), Buffer.byteLength, process.hrtime, logger); } exit() { diff --git a/src/server/session.ts b/src/server/session.ts index 260e3513a0c..821994a6cbb 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -132,6 +132,18 @@ namespace ts.server { export const CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects"; } + export function formatMessage(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string { + const verboseLogging = logger.hasLevel(LogLevel.verbose); + + const json = JSON.stringify(msg); + if (verboseLogging) { + logger.info(msg.type + ": " + json); + } + + const len = byteLength(json, "utf8"); + return `Content-Length: ${1 + len}\r\n\r\n${json}${newLine}`; + } + export class Session { private readonly gcTimer: GcTimer; protected projectService: ProjectService; @@ -145,8 +157,6 @@ namespace ts.server { useSingleInferredProject: boolean, protected readonly typingsInstaller: ITypingsInstaller, private byteLength: (buf: string, encoding?: string) => number, - private maxUncompressedMessageSize: number, - private compress: (s: string) => CompressedData, private hrtime: (start?: number[]) => number[], protected logger: Logger) { this.projectService = @@ -175,27 +185,8 @@ namespace ts.server { this.logger.msg(msg, Msg.Err); } - public send(msg: protocol.Message, canCompressResponse: boolean) { - const verboseLogging = this.logger.hasLevel(LogLevel.verbose); - - const json = JSON.stringify(msg); - if (verboseLogging) { - this.logger.info(msg.type + ": " + json); - } - - const len = this.byteLength(json, "utf8"); - if (len < this.maxUncompressedMessageSize || !canCompressResponse) { - this.host.write(`Content-Length: ${1 + this.byteLength(json, "utf8")}\r\n\r\n${json}${this.host.newLine}`); - } - else { - const start = verboseLogging && this.hrtime(); - const compressed = this.compress(json); - if (verboseLogging) { - const elapsed = this.hrtime(start); - this.logger.info(`compressed message ${json.length} to ${compressed.length} in ${hrTimeToMilliseconds(elapsed)} ms using ${compressed.compressionKind}`); - } - this.host.writeCompressedData(`Content-Length: ${compressed.length + 1} ${compressed.compressionKind}\r\n\r\n`, compressed, this.host.newLine); - } + public send(msg: protocol.Message) { + this.host.write(formatMessage(msg, this.logger, this.byteLength, this.host.newLine)); } public configFileDiagnosticEvent(triggerFile: string, configFile: string, diagnostics: ts.Diagnostic[]) { @@ -210,7 +201,7 @@ namespace ts.server { diagnostics: bakedDiags } }; - this.send(ev, /*canCompressResponse*/ false); + this.send(ev); } public event(info: any, eventName: string) { @@ -220,10 +211,10 @@ namespace ts.server { event: eventName, body: info, }; - this.send(ev, /*canCompressResponse*/ false); + this.send(ev); } - public output(info: any, cmdName: string, canCompressResponse: boolean, reqSeq = 0, errorMsg?: string) { + public output(info: any, cmdName: string, reqSeq = 0, errorMsg?: string) { const res: protocol.Response = { seq: 0, type: "response", @@ -237,7 +228,7 @@ namespace ts.server { else { res.message = errorMsg; } - this.send(res, canCompressResponse); + this.send(res); } private getLocation(position: number, scriptInfo: ScriptInfo): protocol.Location { @@ -1002,7 +993,7 @@ namespace ts.server { this.changeSeq++; // make sure no changes happen before this one is finished if (project.reloadScript(file)) { - this.output(undefined, CommandNames.Reload, /*canCompressResponse*/ false, reqSeq); + this.output(undefined, CommandNames.Reload, reqSeq); } } } @@ -1376,7 +1367,7 @@ namespace ts.server { }, [CommandNames.Configure]: (request: protocol.ConfigureRequest) => { this.projectService.setHostConfiguration(request.arguments); - this.output(undefined, CommandNames.Configure, /*canCompressResponse*/ false, request.seq); + this.output(undefined, CommandNames.Configure, request.seq); return this.notRequired(); }, [CommandNames.Reload]: (request: protocol.ReloadRequest) => { @@ -1446,7 +1437,7 @@ namespace ts.server { } else { this.logger.msg(`Unrecognized JSON command: ${JSON.stringify(request)}`, Msg.Err); - this.output(undefined, CommandNames.Unknown, /*canCompressResponse*/ false, request.seq, `Unrecognized JSON command: ${request.command}`); + this.output(undefined, CommandNames.Unknown, request.seq, `Unrecognized JSON command: ${request.command}`); return { responseRequired: false }; } } @@ -1477,23 +1468,22 @@ namespace ts.server { } if (response) { - this.output(response, request.command, request.canCompressResponse, request.seq); + this.output(response, request.command, request.seq); } else if (responseRequired) { - this.output(undefined, request.command, /*canCompressResponse*/ false, request.seq, "No content available."); + this.output(undefined, request.command, request.seq, "No content available."); } } catch (err) { if (err instanceof OperationCanceledException) { // Handle cancellation exceptions - this.output({ canceled: true }, request.command, /*canCompressResponse*/ false, request.seq); + this.output({ canceled: true }, request.command, request.seq); return; } this.logError(err, message); this.output( undefined, request ? request.command : CommandNames.Unknown, - /*canCompressResponse*/ false, request ? request.seq : 0, "Error processing request. " + (err).message + "\n" + (err).stack); }