290 lines
11 KiB
Plaintext
290 lines
11 KiB
Plaintext
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || (function () {
|
|
var ownKeys = function(o) {
|
|
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
var ar = [];
|
|
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
return ar;
|
|
};
|
|
return ownKeys(o);
|
|
};
|
|
return function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
})();
|
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.StreamMessageWriter = exports.StreamMessageReader = exports.SocketMessageWriter = exports.SocketMessageReader = exports.PortMessageWriter = exports.PortMessageReader = exports.IPCMessageWriter = exports.IPCMessageReader = void 0;
|
|
exports.generateRandomPipeName = generateRandomPipeName;
|
|
exports.createClientPipeTransport = createClientPipeTransport;
|
|
exports.createServerPipeTransport = createServerPipeTransport;
|
|
exports.createClientSocketTransport = createClientSocketTransport;
|
|
exports.createServerSocketTransport = createServerSocketTransport;
|
|
exports.createMessageConnection = createMessageConnection;
|
|
/* --------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
* ----------------------------------------------------------------------------------------- */
|
|
const ril_1 = __importDefault(require("./ril"));
|
|
// Install the node runtime abstract.
|
|
ril_1.default.install();
|
|
const path = __importStar(require("path"));
|
|
const os = __importStar(require("os"));
|
|
const fs = __importStar(require("fs"));
|
|
const crypto_1 = require("crypto");
|
|
const net_1 = require("net");
|
|
const api_1 = require("../common/api");
|
|
__exportStar(require("../common/api"), exports);
|
|
class IPCMessageReader extends api_1.AbstractMessageReader {
|
|
process;
|
|
constructor(process) {
|
|
super();
|
|
this.process = process;
|
|
const eventEmitter = this.process;
|
|
eventEmitter.on('error', (error) => this.fireError(error));
|
|
eventEmitter.on('close', () => this.fireClose());
|
|
}
|
|
listen(callback) {
|
|
this.process.on('message', callback);
|
|
return api_1.Disposable.create(() => this.process.off('message', callback));
|
|
}
|
|
}
|
|
exports.IPCMessageReader = IPCMessageReader;
|
|
class IPCMessageWriter extends api_1.AbstractMessageWriter {
|
|
process;
|
|
errorCount;
|
|
constructor(process) {
|
|
super();
|
|
this.process = process;
|
|
this.errorCount = 0;
|
|
const eventEmitter = this.process;
|
|
eventEmitter.on('error', (error) => this.fireError(error));
|
|
eventEmitter.on('close', () => this.fireClose);
|
|
}
|
|
write(msg) {
|
|
try {
|
|
if (typeof this.process.send === 'function') {
|
|
this.process.send(msg, undefined, undefined, (error) => {
|
|
if (error) {
|
|
this.errorCount++;
|
|
this.handleError(error, msg);
|
|
}
|
|
else {
|
|
this.errorCount = 0;
|
|
}
|
|
});
|
|
}
|
|
return Promise.resolve();
|
|
}
|
|
catch (error) {
|
|
this.handleError(error, msg);
|
|
return Promise.reject(error);
|
|
}
|
|
}
|
|
handleError(error, msg) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
end() {
|
|
}
|
|
}
|
|
exports.IPCMessageWriter = IPCMessageWriter;
|
|
class PortMessageReader extends api_1.AbstractMessageReader {
|
|
onData;
|
|
constructor(port) {
|
|
super();
|
|
this.onData = new api_1.Emitter;
|
|
port.on('close', () => this.fireClose);
|
|
port.on('error', (error) => this.fireError(error));
|
|
port.on('message', (message) => {
|
|
this.onData.fire(message);
|
|
});
|
|
}
|
|
listen(callback) {
|
|
return this.onData.event(callback);
|
|
}
|
|
}
|
|
exports.PortMessageReader = PortMessageReader;
|
|
class PortMessageWriter extends api_1.AbstractMessageWriter {
|
|
port;
|
|
errorCount;
|
|
constructor(port) {
|
|
super();
|
|
this.port = port;
|
|
this.errorCount = 0;
|
|
port.on('close', () => this.fireClose());
|
|
port.on('error', (error) => this.fireError(error));
|
|
}
|
|
write(msg) {
|
|
try {
|
|
this.port.postMessage(msg);
|
|
return Promise.resolve();
|
|
}
|
|
catch (error) {
|
|
this.handleError(error, msg);
|
|
return Promise.reject(error);
|
|
}
|
|
}
|
|
handleError(error, msg) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
end() {
|
|
}
|
|
}
|
|
exports.PortMessageWriter = PortMessageWriter;
|
|
class SocketMessageReader extends api_1.ReadableStreamMessageReader {
|
|
constructor(socket, encoding = 'utf-8') {
|
|
super((0, ril_1.default)().stream.asReadableStream(socket), encoding);
|
|
}
|
|
}
|
|
exports.SocketMessageReader = SocketMessageReader;
|
|
class SocketMessageWriter extends api_1.WriteableStreamMessageWriter {
|
|
socket;
|
|
constructor(socket, options) {
|
|
super((0, ril_1.default)().stream.asWritableStream(socket), options);
|
|
this.socket = socket;
|
|
}
|
|
dispose() {
|
|
super.dispose();
|
|
this.socket.destroy();
|
|
}
|
|
}
|
|
exports.SocketMessageWriter = SocketMessageWriter;
|
|
class StreamMessageReader extends api_1.ReadableStreamMessageReader {
|
|
constructor(readable, encoding) {
|
|
super((0, ril_1.default)().stream.asReadableStream(readable), encoding);
|
|
}
|
|
}
|
|
exports.StreamMessageReader = StreamMessageReader;
|
|
class StreamMessageWriter extends api_1.WriteableStreamMessageWriter {
|
|
constructor(writable, options) {
|
|
super((0, ril_1.default)().stream.asWritableStream(writable), options);
|
|
}
|
|
}
|
|
exports.StreamMessageWriter = StreamMessageWriter;
|
|
const XDG_RUNTIME_DIR = process.env['XDG_RUNTIME_DIR'];
|
|
const safeIpcPathLengths = new Map([
|
|
['linux', 107],
|
|
['darwin', 103]
|
|
]);
|
|
function generateRandomPipeName() {
|
|
if (process.platform === 'win32') {
|
|
return `\\\\.\\pipe\\lsp-${(0, crypto_1.randomBytes)(16).toString('hex')}-sock`;
|
|
}
|
|
let randomLength = 32;
|
|
const fixedLength = '/lsp-.sock'.length;
|
|
const tmpDir = fs.realpathSync(XDG_RUNTIME_DIR ?? os.tmpdir());
|
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
if (limit !== undefined) {
|
|
randomLength = Math.min(limit - tmpDir.length - fixedLength, randomLength);
|
|
}
|
|
if (randomLength < 16) {
|
|
throw new Error(`Unable to generate a random pipe name with ${randomLength} characters.`);
|
|
}
|
|
const randomSuffix = (0, crypto_1.randomBytes)(Math.floor(randomLength / 2)).toString('hex');
|
|
return path.join(tmpDir, `lsp-${randomSuffix}.sock`);
|
|
}
|
|
function createClientPipeTransport(pipeName, encoding = 'utf-8') {
|
|
let connectResolve;
|
|
const connected = new Promise((resolve, _reject) => {
|
|
connectResolve = resolve;
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
const server = (0, net_1.createServer)((socket) => {
|
|
server.close();
|
|
connectResolve([
|
|
new SocketMessageReader(socket, encoding),
|
|
new SocketMessageWriter(socket, encoding)
|
|
]);
|
|
});
|
|
server.on('error', reject);
|
|
server.listen(pipeName, () => {
|
|
server.removeListener('error', reject);
|
|
resolve({
|
|
onConnected: () => { return connected; }
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function createServerPipeTransport(pipeName, encoding = 'utf-8') {
|
|
const socket = (0, net_1.createConnection)(pipeName);
|
|
return [
|
|
new SocketMessageReader(socket, encoding),
|
|
new SocketMessageWriter(socket, encoding)
|
|
];
|
|
}
|
|
function createClientSocketTransport(port, encoding = 'utf-8') {
|
|
let connectResolve;
|
|
const connected = new Promise((resolve, _reject) => {
|
|
connectResolve = resolve;
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
const server = (0, net_1.createServer)((socket) => {
|
|
server.close();
|
|
connectResolve([
|
|
new SocketMessageReader(socket, encoding),
|
|
new SocketMessageWriter(socket, encoding)
|
|
]);
|
|
});
|
|
server.on('error', reject);
|
|
server.listen(port, '127.0.0.1', () => {
|
|
server.removeListener('error', reject);
|
|
resolve({
|
|
onConnected: () => { return connected; }
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function createServerSocketTransport(port, encoding = 'utf-8') {
|
|
const socket = (0, net_1.createConnection)(port, '127.0.0.1');
|
|
return [
|
|
new SocketMessageReader(socket, encoding),
|
|
new SocketMessageWriter(socket, encoding)
|
|
];
|
|
}
|
|
function isReadableStream(value) {
|
|
const candidate = value;
|
|
return candidate.read !== undefined && candidate.addListener !== undefined;
|
|
}
|
|
function isWritableStream(value) {
|
|
const candidate = value;
|
|
return candidate.write !== undefined && candidate.addListener !== undefined;
|
|
}
|
|
function createMessageConnection(input, output, logger, options) {
|
|
if (!logger) {
|
|
logger = api_1.NullLogger;
|
|
}
|
|
const reader = isReadableStream(input) ? new StreamMessageReader(input) : input;
|
|
const writer = isWritableStream(output) ? new StreamMessageWriter(output) : output;
|
|
if (api_1.ConnectionStrategy.is(options)) {
|
|
options = { connectionStrategy: options };
|
|
}
|
|
return (0, api_1.createMessageConnection)(reader, writer, logger, options);
|
|
}
|