use local tsserverForkStart

This commit is contained in:
chemzqm 2019-04-19 20:56:00 +08:00
parent 6af7cf518a
commit 7563b04482
2 changed files with 162 additions and 1 deletions

161
bin/tsserverForkStart.js Normal file
View file

@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
let net = require('net');
let fs = require('fs');
let ENABLE_LOGGING = false;
let log = (function () {
if (!ENABLE_LOGGING) {
return function () { }; // tslint:disable-line
}
let isFirst = true;
let LOG_LOCATION = 'C:\\stdFork.log';
return function log(str) {
if (isFirst) {
isFirst = false;
fs.writeFileSync(LOG_LOCATION, str + '\n');
return;
}
fs.appendFileSync(LOG_LOCATION, str + '\n');
};
})();
let stdInPipeName = process.env['STDIN_PIPE_NAME']; // tslint:disable-line
let stdOutPipeName = process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
let stdErrPipeName = process.env['STDERR_PIPE_NAME']; // tslint:disable-line
log('STDIN_PIPE_NAME: ' + stdInPipeName);
log('STDOUT_PIPE_NAME: ' + stdOutPipeName);
log('STDERR_PIPE_NAME: ' + stdErrPipeName);
(function () {
log('Beginning stdout redirection...');
// Create a writing stream to the stdout pipe
let stdOutStream = net.connect(stdOutPipeName);
// unref stdOutStream to behave like a normal standard out
stdOutStream.unref();
process.__defineGetter__('stdout', function () {
return stdOutStream;
});
// Create a writing stream to the stderr pipe
let stdErrStream = net.connect(stdErrPipeName);
// unref stdErrStream to behave like a normal standard out
stdErrStream.unref();
process.__defineGetter__('stderr', function () {
return stdErrStream;
});
let fsWriteSyncString = function (// tslint:disable-line
fd, str, _position, encoding) {
// fs.writeSync(fd, string[, position[, encoding]])
let buf = Buffer.from(str, encoding || 'utf8');
return fsWriteSyncBuffer(fd, buf, 0, buf.length); // tslint:disable-line
};
let fsWriteSyncBuffer = function (// tslint:disable-line
fd, buffer, off, len) {
off = Math.abs(off | 0);
len = Math.abs(len | 0);
// fs.writeSync(fd, buffer, offset, length[, position])
let buffer_length = buffer.length;
if (off > buffer_length) {
throw new Error('offset out of bounds');
}
if (len > buffer_length) {
throw new Error('length out of bounds');
}
if (((off + len) | 0) < off) {
throw new Error('off + len overflow');
}
if (buffer_length - off < len) {
// Asking for more than is left over in the buffer
throw new Error('off + len > buffer.length');
}
let slicedBuffer = buffer;
if (off !== 0 || len !== buffer_length) {
slicedBuffer = buffer.slice(off, off + len);
}
if (fd === 1) {
stdOutStream.write(slicedBuffer);
}
else {
stdErrStream.write(slicedBuffer);
}
return slicedBuffer.length;
};
// handle fs.writeSync(1, ...)
let originalWriteSync = fs.writeSync;
fs.writeSync = function (// tslint:disable-line
fd, data, _position, _encoding) {
if (fd !== 1 && fd !== 2) {
return originalWriteSync.apply(fs, arguments);
}
// usage:
// fs.writeSync(fd, buffer, offset, length[, position])
// OR
// fs.writeSync(fd, string[, position[, encoding]])
if (data instanceof Buffer) {
return fsWriteSyncBuffer.apply(null, arguments);
}
// For compatibility reasons with fs.writeSync, writing null will write "null", etc
if (typeof data !== 'string') {
data += '';
}
return fsWriteSyncString.apply(null, arguments);
};
log('Finished defining process.stdout, process.stderr and fs.writeSync');
})();
(function () {
// Begin listening to stdin pipe
let server = net.createServer(function (stream) {
// Stop accepting new connections, keep the existing one alive
server.close();
log('Parent process has connected to my stdin. All should be good now.');
process.__defineGetter__('stdin', function () {
return stream;
});
// Remove myself from process.argv
process.argv.splice(1, 1);
// Load the actual program
let program = process.argv[1];
log('Loading program: ' + program);
// Unset the custom environmental variables that should not get inherited
delete process.env['STDIN_PIPE_NAME']; // tslint:disable-line
delete process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
delete process.env['STDERR_PIPE_NAME']; // tslint:disable-line
require(program);
log('Finished loading program.');
let stdinIsReferenced = true;
let timer = setInterval(function () {
let listenerCount = stream.listeners('data').length +
stream.listeners('end').length +
stream.listeners('close').length +
stream.listeners('error').length;
// log('listenerCount: ' + listenerCount)
if (listenerCount <= 1) {
// No more "actual" listeners, only internal node
if (stdinIsReferenced) {
stdinIsReferenced = false;
// log('unreferencing stream!!!')
stream.unref();
}
}
else {
// There are "actual" listeners
if (!stdinIsReferenced) {
stdinIsReferenced = true;
stream.ref();
}
}
// log(
// '' + stream.listeners('data').length +
// ' ' + stream.listeners('end').length +
// ' ' + stream.listeners('close').length +
// ' ' + stream.listeners('error').length
// )
}, 1000);
if (timer.unref) { // tslint:disable-line
timer.unref(); // tslint:disable-line
}
});
server.listen(stdInPipeName, function () {
// signal via stdout that the parent process can now begin writing to stdin pipe
process.stdout.write('ready');
});
})();

View file

@ -135,7 +135,7 @@ export function fork(
// Create the process
logger.info('Forking TSServer', `PATH: ${newEnv['PATH']} `)
const bootstrapperPath = path.join(workspace.pluginRoot, 'bin/tsserverForkStart')
const bootstrapperPath = path.resolve(__dirname, '../../../bin/tsserverForkStart')
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
silent: true,
env: newEnv,