Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -151,20 +151,16 @@ export class ConfigWatcher<T> implements IConfigWatcher<T>, IDisposable {
return; // avoid watchers that will never get disposed by checking for being disposed
}
try {
const watcher = extfs.watch(path, (type, file) => this.onConfigFileChange(type, file, isParentFolder));
watcher.on('error', (code: number, signal: string) => this.options.onError(`Error watching ${path} for configuration changes (${code}, ${signal})`));
const watcher = extfs.watch(path,
(type, file) => this.onConfigFileChange(type, file, isParentFolder),
(error: string) => this.options.onError(error)
);
if (watcher) {
this.disposables.push(toDisposable(() => {
watcher.removeAllListeners();
watcher.close();
}));
} catch (error) {
fs.exists(path, exists => {
if (exists) {
this.options.onError(`Failed to watch ${path} for configuration changes (${error.toString()})`);
}
});
}
}

View File

@@ -69,7 +69,7 @@ export function getFirstFrame(arg0: IRemoteConsoleLog | string): IStackFrame {
// at e.$executeContributedCommand(c:\Users\someone\Desktop\end-js\extension.js:19:17)
const stack = arg0;
if (stack) {
const topFrame = stack.split('\n')[0];
const topFrame = findFirstFrame(stack);
// at [^\/]* => line starts with "at" followed by any character except '/' (to not capture unix paths too late)
// (?:(?:[a-zA-Z]+:)|(?:[\/])|(?:\\\\) => windows drive letter OR unix root OR unc root
@@ -88,12 +88,25 @@ export function getFirstFrame(arg0: IRemoteConsoleLog | string): IStackFrame {
return void 0;
}
function findFirstFrame(stack: string): string {
if (!stack) {
return stack;
}
const newlineIndex = stack.indexOf('\n');
if (newlineIndex === -1) {
return stack;
}
return stack.substring(0, newlineIndex);
}
export function log(entry: IRemoteConsoleLog, label: string): void {
const { args, stack } = parse(entry);
const isOneStringArg = typeof args[0] === 'string' && args.length === 1;
let topFrame = stack && stack.split('\n')[0];
let topFrame = findFirstFrame(stack);
if (topFrame) {
topFrame = `(${topFrame.trim()})`;
}

View File

@@ -28,11 +28,11 @@ export function bomLength(encoding: string): number {
return 0;
}
export function decode(buffer: NodeBuffer, encoding: string, options?: any): string {
return iconv.decode(buffer, toNodeEncoding(encoding), options);
export function decode(buffer: NodeBuffer, encoding: string): string {
return iconv.decode(buffer, toNodeEncoding(encoding));
}
export function encode(content: string, encoding: string, options?: any): NodeBuffer {
export function encode(content: string | NodeBuffer, encoding: string, options?: { addBOM?: boolean }): NodeBuffer {
return iconv.encode(content, toNodeEncoding(encoding), options);
}
@@ -44,6 +44,10 @@ export function decodeStream(encoding: string): NodeJS.ReadWriteStream {
return iconv.decodeStream(toNodeEncoding(encoding));
}
export function encodeStream(encoding: string, options?: { addBOM?: boolean }): NodeJS.ReadWriteStream {
return iconv.encodeStream(toNodeEncoding(encoding), options);
}
function toNodeEncoding(enc: string): string {
if (enc === UTF8_with_bom) {
return UTF8; // iconv does not distinguish UTF 8 with or without BOM, so we need to help it
@@ -181,6 +185,7 @@ const windowsTerminalEncodings = {
'865': 'cp865', // Nordic
'866': 'cp866', // Russian
'869': 'cp869', // Modern Greek
'936': 'cp936', // Simplified Chinese
'1252': 'cp1252' // West European Latin
};

View File

@@ -9,11 +9,11 @@ import * as uuid from 'vs/base/common/uuid';
import * as strings from 'vs/base/common/strings';
import * as platform from 'vs/base/common/platform';
import * as flow from 'vs/base/node/flow';
import * as fs from 'fs';
import * as paths from 'path';
import { TPromise } from 'vs/base/common/winjs.base';
import { nfcall } from 'vs/base/common/async';
import { encode, encodeStream } from 'vs/base/node/encoding';
const loop = flow.loop;
@@ -43,6 +43,27 @@ export function readdir(path: string, callback: (error: Error, files: string[])
return fs.readdir(path, callback);
}
export interface IStatAndLink {
stat: fs.Stats;
isSymbolicLink: boolean;
}
export function statLink(path: string, callback: (error: Error, statAndIsLink: IStatAndLink) => void): void {
fs.lstat(path, (error, lstat) => {
if (error || lstat.isSymbolicLink()) {
fs.stat(path, (error, stat) => {
if (error) {
return callback(error, null);
}
callback(null, { stat, isSymbolicLink: lstat && lstat.isSymbolicLink() });
});
} else {
callback(null, { stat: lstat, isSymbolicLink: false });
}
});
}
export function copy(source: string, target: string, callback: (error: Error) => void, copiedSources?: { [path: string]: boolean }): void {
if (!copiedSources) {
copiedSources = Object.create(null);
@@ -54,7 +75,7 @@ export function copy(source: string, target: string, callback: (error: Error) =>
}
if (!stat.isDirectory()) {
return pipeFs(source, target, stat.mode & 511, callback);
return doCopyFile(source, target, stat.mode & 511, callback);
}
if (copiedSources[source]) {
@@ -75,6 +96,38 @@ export function copy(source: string, target: string, callback: (error: Error) =>
});
}
function doCopyFile(source: string, target: string, mode: number, callback: (error: Error) => void): void {
const reader = fs.createReadStream(source);
const writer = fs.createWriteStream(target, { mode });
let finished = false;
const finish = (error?: Error) => {
if (!finished) {
finished = true;
// in error cases, pass to callback
if (error) {
callback(error);
}
// we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104
else {
fs.chmod(target, mode, callback);
}
}
};
// handle errors properly
reader.once('error', error => finish(error));
writer.once('error', error => finish(error));
// we are done (underlying fd has been closed)
writer.once('close', () => finish());
// start piping
reader.pipe(writer);
}
export function mkdirp(path: string, mode?: number): TPromise<boolean> {
const mkdir = () => nfcall(fs.mkdir, path, mode)
.then(null, (err: NodeJS.ErrnoException) => {
@@ -88,11 +141,12 @@ export function mkdirp(path: string, mode?: number): TPromise<boolean> {
return TPromise.wrapError<boolean>(err);
});
// is root?
// stop at root
if (path === paths.dirname(path)) {
return TPromise.as(true);
}
// recursively mkdir
return mkdir().then(null, (err: NodeJS.ErrnoException) => {
if (err.code === 'ENOENT') {
return mkdirp(paths.dirname(path), mode).then(mkdir);
@@ -102,40 +156,6 @@ export function mkdirp(path: string, mode?: number): TPromise<boolean> {
});
}
function pipeFs(source: string, target: string, mode: number, callback: (error: Error) => void): void {
let callbackHandled = false;
const readStream = fs.createReadStream(source);
const writeStream = fs.createWriteStream(target, { mode: mode });
const onError = (error: Error) => {
if (!callbackHandled) {
callbackHandled = true;
callback(error);
}
};
readStream.on('error', onError);
writeStream.on('error', onError);
readStream.on('end', () => {
(<any>writeStream).end(() => { // In this case the write stream is known to have an end signature with callback
if (!callbackHandled) {
callbackHandled = true;
fs.chmod(target, mode, callback); // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104
}
});
});
// In node 0.8 there is no easy way to find out when the pipe operation has finished. As such, we use the end property = false
// so that we are in charge of calling end() on the write stream and we will be notified when the write stream is really done.
// We can do this because file streams have an end() method that allows to pass in a callback.
// In node 0.10 there is an event 'finish' emitted from the write stream that can be used. See
// https://groups.google.com/forum/?fromgroups=#!topic/nodejs/YWQ1sRoXOdI
readStream.pipe(writeStream, { end: false });
}
// Deletes the given path by first moving it out of the workspace. This has two benefits. For one, the operation can return fast because
// after the rename, the contents are out of the workspace although not yet deleted. The greater benefit however is that this operation
// will fail in case any file is used by another process. fs.unlink() in node will not bail if a file unlinked is used by another process.
@@ -320,19 +340,124 @@ export function mv(source: string, target: string, callback: (error: Error) => v
});
}
export interface IWriteFileOptions {
mode?: number;
flag?: string;
encoding?: {
charset: string;
addBOM: boolean;
};
}
let canFlush = true;
export function writeFileAndFlush(path: string, data: string | NodeBuffer | NodeJS.ReadableStream, options: IWriteFileOptions, callback: (error?: Error) => void): void {
options = ensureOptions(options);
if (typeof data === 'string' || Buffer.isBuffer(data)) {
doWriteFileAndFlush(path, data, options, callback);
} else {
doWriteFileStreamAndFlush(path, data, options, callback);
}
}
function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream, options: IWriteFileOptions, callback: (error?: Error) => void): void {
// finish only once
let finished = false;
const finish = (error?: Error) => {
if (!finished) {
finished = true;
// in error cases we need to manually close streams
// if the write stream was successfully opened
if (error) {
if (isOpen) {
writer.once('close', () => callback(error));
writer.close();
} else {
callback(error);
}
}
// otherwise just return without error
else {
callback();
}
}
};
// create writer to target. we set autoClose: false because we want to use the streams
// file descriptor to call fs.fdatasync to ensure the data is flushed to disk
const writer = fs.createWriteStream(path, { mode: options.mode, flags: options.flag, autoClose: false });
// Event: 'open'
// Purpose: save the fd for later use and start piping
// Notes: will not be called when there is an error opening the file descriptor!
let fd: number;
let isOpen: boolean;
writer.once('open', descriptor => {
fd = descriptor;
isOpen = true;
// if an encoding is provided, we need to pipe the stream through
// an encoder stream and forward the encoding related options
if (options.encoding) {
reader = reader.pipe(encodeStream(options.encoding.charset, { addBOM: options.encoding.addBOM }));
}
// start data piping only when we got a successful open. this ensures that we do
// not consume the stream when an error happens and helps to fix this issue:
// https://github.com/Microsoft/vscode/issues/42542
reader.pipe(writer);
});
// Event: 'error'
// Purpose: to return the error to the outside and to close the write stream (does not happen automatically)
reader.once('error', error => finish(error));
writer.once('error', error => finish(error));
// Event: 'finish'
// Purpose: use fs.fdatasync to flush the contents to disk
// Notes: event is called when the writer has finished writing to the underlying resource. we must call writer.close()
// because we have created the WriteStream with autoClose: false
writer.once('finish', () => {
// flush to disk
if (canFlush && isOpen) {
fs.fdatasync(fd, (syncError: Error) => {
// In some exotic setups it is well possible that node fails to sync
// In that case we disable flushing and warn to the console
if (syncError) {
console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError);
canFlush = false;
}
writer.close();
});
} else {
writer.close();
}
});
// Event: 'close'
// Purpose: signal we are done to the outside
// Notes: event is called when the writer's filedescriptor is closed
writer.once('close', () => finish());
}
// Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk
// We do this in cases where we want to make sure the data is really on disk and
// not in some cache.
//
// See https://github.com/nodejs/node/blob/v5.10.0/lib/fs.js#L1194
let canFlush = true;
export function writeFileAndFlush(path: string, data: string | NodeBuffer, options: { mode?: number; flag?: string; }, callback: (error: Error) => void): void {
if (!canFlush) {
return fs.writeFile(path, data, options, callback);
function doWriteFileAndFlush(path: string, data: string | NodeBuffer, options: IWriteFileOptions, callback: (error?: Error) => void): void {
if (options.encoding) {
data = encode(data, options.encoding.charset, { addBOM: options.encoding.addBOM });
}
if (!options) {
options = { mode: 0o666, flag: 'w' };
if (!canFlush) {
return fs.writeFile(path, data, { mode: options.mode, flag: options.flag }, callback);
}
// Open the file with same flags and mode as fs.writeFile()
@@ -363,13 +488,15 @@ export function writeFileAndFlush(path: string, data: string | NodeBuffer, optio
});
}
export function writeFileAndFlushSync(path: string, data: string | NodeBuffer, options?: { mode?: number; flag?: string; }): void {
if (!canFlush) {
return fs.writeFileSync(path, data, options);
export function writeFileAndFlushSync(path: string, data: string | NodeBuffer, options?: IWriteFileOptions): void {
options = ensureOptions(options);
if (options.encoding) {
data = encode(data, options.encoding.charset, { addBOM: options.encoding.addBOM });
}
if (!options) {
options = { mode: 0o666, flag: 'w' };
if (!canFlush) {
return fs.writeFileSync(path, data, { mode: options.mode, flag: options.flag });
}
// Open the file with same flags and mode as fs.writeFile()
@@ -392,6 +519,24 @@ export function writeFileAndFlushSync(path: string, data: string | NodeBuffer, o
}
}
function ensureOptions(options?: IWriteFileOptions): IWriteFileOptions {
if (!options) {
return { mode: 0o666, flag: 'w' };
}
const ensuredOptions: IWriteFileOptions = { mode: options.mode, flag: options.flag, encoding: options.encoding };
if (typeof ensuredOptions.mode !== 'number') {
ensuredOptions.mode = 0o666;
}
if (typeof ensuredOptions.flag !== 'string') {
ensuredOptions.flag = 'w';
}
return ensuredOptions;
}
/**
* Copied from: https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/pathUtilities.ts#L83
*
@@ -474,21 +619,34 @@ function normalizePath(path: string): string {
return strings.rtrim(paths.normalize(path), paths.sep);
}
export function watch(path: string, onChange: (type: string, path: string) => void): fs.FSWatcher {
const watcher = fs.watch(path);
watcher.on('change', (type, raw) => {
let file: string = null;
if (raw) { // https://github.com/Microsoft/vscode/issues/38191
file = raw.toString();
if (platform.isMacintosh) {
// Mac: uses NFD unicode form on disk, but we want NFC
// See also https://github.com/nodejs/node/issues/2165
file = strings.normalizeNFC(file);
export function watch(path: string, onChange: (type: string, path: string) => void, onError: (error: string) => void): fs.FSWatcher {
try {
const watcher = fs.watch(path);
watcher.on('change', (type, raw) => {
let file: string = null;
if (raw) { // https://github.com/Microsoft/vscode/issues/38191
file = raw.toString();
if (platform.isMacintosh) {
// Mac: uses NFD unicode form on disk, but we want NFC
// See also https://github.com/nodejs/node/issues/2165
file = strings.normalizeNFC(file);
}
}
}
onChange(type, file);
});
onChange(type, file);
});
return watcher;
}
watcher.on('error', (code: number, signal: string) => onError(`Failed to watch ${path} for changes (${code}, ${signal})`));
return watcher;
} catch (error) {
fs.exists(path, exists => {
if (exists) {
onError(`Failed to watch ${path} for changes (${error.toString()})`);
}
});
}
return void 0;
}

View File

@@ -19,7 +19,7 @@ export function readdir(path: string): TPromise<string[]> {
}
export function exists(path: string): TPromise<boolean> {
return new TPromise(c => fs.exists(path, c));
return new TPromise(c => fs.exists(path, c), () => { });
}
export function chmod(path: string, mode: number): TPromise<boolean> {
@@ -54,6 +54,10 @@ export function stat(path: string): TPromise<fs.Stats> {
return nfcall(fs.stat, path);
}
export function statLink(path: string): TPromise<{ stat: fs.Stats, isSymbolicLink: boolean }> {
return nfcall(extfs.statLink, path);
}
export function lstat(path: string): TPromise<fs.Stats> {
return nfcall(fs.lstat, path);
}
@@ -99,10 +103,11 @@ export function readFile(path: string, encoding?: string): TPromise<Buffer | str
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly.
const writeFilePathQueue: { [path: string]: Queue<void> } = Object.create(null);
export function writeFile(path: string, data: string, options?: { mode?: number; flag?: string; }): TPromise<void>;
export function writeFile(path: string, data: NodeBuffer, options?: { mode?: number; flag?: string; }): TPromise<void>;
export function writeFile(path: string, data: any, options?: { mode?: number; flag?: string; }): TPromise<void> {
let queueKey = toQueueKey(path);
export function writeFile(path: string, data: string, options?: extfs.IWriteFileOptions): TPromise<void>;
export function writeFile(path: string, data: NodeBuffer, options?: extfs.IWriteFileOptions): TPromise<void>;
export function writeFile(path: string, data: NodeJS.ReadableStream, options?: extfs.IWriteFileOptions): TPromise<void>;
export function writeFile(path: string, data: any, options?: extfs.IWriteFileOptions): TPromise<void> {
const queueKey = toQueueKey(path);
return ensureWriteFileQueue(queueKey).queue(() => nfcall(extfs.writeFileAndFlush, path, data, options));
}
@@ -160,8 +165,14 @@ export function fileExists(path: string): TPromise<boolean> {
/**
* Deletes a path from disk.
*/
const tmpDir = os.tmpdir();
export function del(path: string, tmp = tmpDir): TPromise<void> {
let _tmpDir: string = null;
function getTmpDir(): string {
if (!_tmpDir) {
_tmpDir = os.tmpdir();
}
return _tmpDir;
}
export function del(path: string, tmp = getTmpDir()): TPromise<void> {
return nfcall(extfs.del, path, tmp);
}
@@ -184,4 +195,4 @@ export function whenDeleted(path: string): TPromise<void> {
}
}, 1000);
});
}
}

View File

@@ -7,6 +7,15 @@
import net = require('net');
/**
* @returns Returns a random port between 1025 and 65535.
*/
export function randomPort(): number {
let min = 1025;
let max = 65535;
return min + Math.floor((max - min) * Math.random());
}
/**
* Given a start point and a max number of retries, will find a port that
* is openable. Will return 0 in case no free port can be found.

View File

@@ -6,9 +6,6 @@
import path = require('path');
import * as cp from 'child_process';
import ChildProcess = cp.ChildProcess;
import exec = cp.exec;
import spawn = cp.spawn;
import { fork } from 'vs/base/node/stdFork';
import nls = require('vs/nls');
import { PPromise, TPromise, TValueCallback, TProgressCallback, ErrorCallback } from 'vs/base/common/winjs.base';
@@ -40,7 +37,7 @@ function getWindowsCode(status: number): TerminateResponseCode {
}
}
export function terminateProcess(process: ChildProcess, cwd?: string): TerminateResponse {
export function terminateProcess(process: cp.ChildProcess, cwd?: string): TerminateResponse {
if (Platform.isWindows) {
try {
let options: any = {
@@ -80,8 +77,8 @@ export abstract class AbstractProcess<TProgressData> {
private options: CommandOptions | ForkOptions;
protected shell: boolean;
private childProcess: ChildProcess;
protected childProcessPromise: TPromise<ChildProcess>;
private childProcess: cp.ChildProcess;
protected childProcessPromise: TPromise<cp.ChildProcess>;
protected terminateRequested: boolean;
private static WellKnowCommands: IStringDictionary<boolean> = {
@@ -173,7 +170,7 @@ export abstract class AbstractProcess<TProgressData> {
if (this.args) {
cmd = cmd + ' ' + this.args.join(' ');
}
this.childProcess = exec(cmd, this.options, (error, stdout, stderr) => {
this.childProcess = cp.exec(cmd, this.options, (error, stdout, stderr) => {
this.childProcess = null;
let err: any = error;
// This is tricky since executing a command shell reports error back in case the executed command return an
@@ -186,7 +183,7 @@ export abstract class AbstractProcess<TProgressData> {
}
});
} else {
let childProcess: ChildProcess = null;
let childProcess: cp.ChildProcess = null;
let closeHandler = (data: any) => {
this.childProcess = null;
this.childProcessPromise = null;
@@ -231,13 +228,13 @@ export abstract class AbstractProcess<TProgressData> {
} else {
args.push(commandLine.join(' '));
}
childProcess = spawn(getWindowsShell(), args, options);
childProcess = cp.spawn(getWindowsShell(), args, options);
} else {
if (this.cmd) {
childProcess = spawn(this.cmd, this.args, this.options);
childProcess = cp.spawn(this.cmd, this.args, this.options);
} else if (this.module) {
this.childProcessPromise = new TPromise<ChildProcess>((c, e, p) => {
fork(this.module, this.args, <ForkOptions>this.options, (error: any, childProcess: ChildProcess) => {
this.childProcessPromise = new TPromise<cp.ChildProcess>((c, e, p) => {
fork(this.module, this.args, <ForkOptions>this.options, (error: any, childProcess: cp.ChildProcess) => {
if (error) {
e(error);
ee({ terminated: this.terminateRequested, error: error });
@@ -269,7 +266,7 @@ export abstract class AbstractProcess<TProgressData> {
}
protected abstract handleExec(cc: TValueCallback<SuccessData>, pp: TProgressCallback<TProgressData>, error: Error, stdout: Buffer, stderr: Buffer): void;
protected abstract handleSpawn(childProcess: ChildProcess, cc: TValueCallback<SuccessData>, pp: TProgressCallback<TProgressData>, ee: ErrorCallback, sync: boolean): void;
protected abstract handleSpawn(childProcess: cp.ChildProcess, cc: TValueCallback<SuccessData>, pp: TProgressCallback<TProgressData>, ee: ErrorCallback, sync: boolean): void;
protected handleClose(data: any, cc: TValueCallback<SuccessData>, pp: TProgressCallback<TProgressData>, ee: ErrorCallback): void {
// Default is to do nothing.
@@ -315,7 +312,7 @@ export abstract class AbstractProcess<TProgressData> {
if (!this.shell || !Platform.isWindows) {
c(false);
}
let cmdShell = spawn(getWindowsShell(), ['/s', '/c']);
let cmdShell = cp.spawn(getWindowsShell(), ['/s', '/c']);
cmdShell.on('error', (error: Error) => {
c(true);
});
@@ -353,7 +350,7 @@ export class LineProcess extends AbstractProcess<LineData> {
cc({ terminated: this.terminateRequested, error: error });
}
protected handleSpawn(childProcess: ChildProcess, cc: TValueCallback<SuccessData>, pp: TProgressCallback<LineData>, ee: ErrorCallback, sync: boolean): void {
protected handleSpawn(childProcess: cp.ChildProcess, cc: TValueCallback<SuccessData>, pp: TProgressCallback<LineData>, ee: ErrorCallback, sync: boolean): void {
this.stdoutLineDecoder = new LineDecoder();
this.stderrLineDecoder = new LineDecoder();
childProcess.stdout.on('data', (data: Buffer) => {
@@ -384,7 +381,7 @@ export interface IQueuedSender {
// queue is free again to consume messages.
// On Windows we always wait for the send() method to return before sending the next message
// to workaround https://github.com/nodejs/node/issues/7657 (IPC can freeze process)
export function createQueuedSender(childProcess: ChildProcess | NodeJS.Process): IQueuedSender {
export function createQueuedSender(childProcess: cp.ChildProcess | NodeJS.Process): IQueuedSender {
let msgQueue: string[] = [];
let useQueue = false;

View File

@@ -7,6 +7,7 @@
import { spawn, exec } from 'child_process';
import * as path from 'path';
import * as nls from 'vs/nls';
import URI from 'vs/base/common/uri';
export interface ProcessItem {
@@ -61,12 +62,30 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
function findName(cmd: string): string {
const RENDERER_PROCESS_HINT = /--disable-blink-features=Auxclick/;
const WINDOWS_WATCHER_HINT = /\\watcher\\win32\\CodeHelper.exe/;
const WINDOWS_WATCHER_HINT = /\\watcher\\win32\\CodeHelper\.exe/;
const WINDOWS_CRASH_REPORTER = /--crashes-directory/;
const WINDOWS_PTY = /\\pipe\\winpty-control/;
const WINDOWS_CONSOLE_HOST = /conhost\.exe/;
const TYPE = /--type=([a-zA-Z-]+)/;
// find windows file watcher
if (WINDOWS_WATCHER_HINT.exec(cmd)) {
return 'watcherService';
return 'watcherService ';
}
// find windows crash reporter
if (WINDOWS_CRASH_REPORTER.exec(cmd)) {
return 'electron-crash-reporter';
}
// find windows pty process
if (WINDOWS_PTY.exec(cmd)) {
return 'winpty-process';
}
//find windows console host process
if (WINDOWS_CONSOLE_HOST.exec(cmd)) {
return 'console-window-host (Windows internal process)';
}
// find "--type=xxxx"
@@ -102,6 +121,8 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
if (process.platform === 'win32') {
console.log(nls.localize('collecting', 'Collecting CPU and memory information. This might take a couple of seconds.'));
interface ProcessInfo {
type: 'processInfo';
name: string;
@@ -157,7 +178,8 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
cmd.on('exit', () => {
if (stderr.length > 0) {
reject(stderr);
reject(new Error(stderr));
return;
}
let processItems: Map<number, ProcessItem> = new Map();
try {
@@ -205,12 +227,13 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
reject(new Error(`Root process ${rootPid} not found`));
}
} catch (error) {
console.log(stdout);
reject(error);
}
});
} else { // OS X & Linux
const CMD = 'ps -ax -o pid=,ppid=,pcpu=,pmem=,command=';
const CMD = '/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=';
const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/;
exec(CMD, { maxBuffer: 1000 * 1024 }, (err, stdout, stderr) => {

View File

@@ -28,7 +28,7 @@ export interface IRequestOptions {
password?: string;
headers?: any;
timeout?: number;
data?: any;
data?: string | Stream;
agent?: Agent;
followRedirects?: number;
strictSSL?: boolean;
@@ -63,6 +63,7 @@ export function request(options: IRequestOptions): TPromise<IRequestContext> {
: getNodeRequest(options);
return rawRequestPromise.then(rawRequest => {
return new TPromise<IRequestContext>((c, e) => {
const endpoint = parseUrl(options.url);
@@ -83,7 +84,6 @@ export function request(options: IRequestOptions): TPromise<IRequestContext> {
req = rawRequest(opts, (res: http.ClientResponse) => {
const followRedirects = isNumber(options.followRedirects) ? options.followRedirects : 3;
if (res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) {
request(assign({}, options, {
url: res.headers['location'],
@@ -107,7 +107,12 @@ export function request(options: IRequestOptions): TPromise<IRequestContext> {
}
if (options.data) {
req.write(options.data);
if (typeof options.data === 'string') {
req.write(options.data);
} else {
options.data.pipe(req);
return;
}
}
req.end();
@@ -167,7 +172,13 @@ export function asJson<T>(context: IRequestContext): TPromise<T> {
const buffer: string[] = [];
context.stream.on('data', (d: string) => buffer.push(d));
context.stream.on('end', () => c(JSON.parse(buffer.join(''))));
context.stream.on('end', () => {
try {
c(JSON.parse(buffer.join('')));
} catch (err) {
e(err);
}
});
context.stream.on('error', e);
});
}

View File

@@ -79,12 +79,12 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Workspa
const MAX_FILES = 20000;
let walkSync = (dir: string, acceptFile: (fileName: string) => void, filter: string[], token) => {
if (token.maxReached) {
return;
}
try {
let files = readdirSync(dir);
for (const file of files) {
if (token.maxReached) {
return;
}
try {
if (statSync(join(dir, file)).isDirectory()) {
if (filter.indexOf(file) === -1) {
@@ -92,10 +92,11 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Workspa
}
}
else {
if (token.count++ >= MAX_FILES) {
if (token.count >= MAX_FILES) {
token.maxReached = true;
return;
}
token.count++;
acceptFile(file);
}
} catch {

View File

@@ -50,7 +50,6 @@ function generatePatchedEnv(env: any, stdInPipeName: string, stdOutPipeName: str
newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName;
newEnv['STDERR_PIPE_NAME'] = stdErrPipeName;
newEnv['ELECTRON_RUN_AS_NODE'] = '1';
newEnv['ELECTRON_NO_ASAR'] = '1';
return newEnv;
}
@@ -138,4 +137,4 @@ export function fork(modulePath: string, args: string[], options: IForkOpts, cal
// On vscode exit still close server #7758
process.once('exit', closeServer);
}
}

View File

@@ -59,7 +59,7 @@ log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']);
var fsWriteSyncString = function (fd, str, position, encoding) {
// fs.writeSync(fd, string[, position[, encoding]]);
var buf = new Buffer(str, encoding || 'utf8');
var buf = Buffer.from(str, encoding || 'utf8');
return fsWriteSyncBuffer(fd, buf, 0, buf.length);
};

View File

@@ -38,7 +38,7 @@ export function readExactlyByFile(file: string, totalBytes: number): TPromise<Re
});
}
const buffer = new Buffer(totalBytes);
const buffer = Buffer.allocUnsafe(totalBytes);
let offset = 0;
function readChunk(): void {
@@ -96,7 +96,7 @@ export function readToMatchingString(file: string, matchingString: string, chunk
});
}
let buffer = new Buffer(maximumBytesToRead);
let buffer = Buffer.allocUnsafe(maximumBytesToRead);
let offset = 0;
function readChunk(): void {

View File

@@ -10,7 +10,7 @@ import { Readable } from 'stream';
import { nfcall, ninvoke, SimpleThrottler } from 'vs/base/common/async';
import { mkdirp, rimraf } from 'vs/base/node/pfs';
import { TPromise } from 'vs/base/common/winjs.base';
import { open as openZip, Entry, ZipFile } from 'yauzl';
import { open as _openZip, Entry, ZipFile } from 'yauzl';
export interface IExtractOptions {
overwrite?: boolean;
@@ -26,6 +26,29 @@ interface IOptions {
sourcePathRegex: RegExp;
}
export enum ExtractErrorType {
Undefined,
CorruptZip
}
export class ExtractError extends Error {
readonly type: ExtractErrorType;
readonly cause: Error;
constructor(type: ExtractErrorType, cause: Error) {
let message = cause.message;
switch (type) {
case ExtractErrorType.CorruptZip: message = `Corrupt ZIP: ${message}`; break;
}
super(message);
this.type = type;
this.cause = cause;
}
}
function modeFromEntry(entry: Entry) {
let attr = entry.externalFileAttributes >> 16 || 33188;
@@ -34,6 +57,18 @@ function modeFromEntry(entry: Entry) {
.reduce((a, b) => a + b, attr & 61440 /* S_IFMT */);
}
function toExtractError(err: Error): ExtractError {
let type = ExtractErrorType.CorruptZip;
console.log('WHAT');
if (/end of central directory record signature not found/.test(err.message)) {
type = ExtractErrorType.CorruptZip;
}
return new ExtractError(type, err);
}
function extractEntry(stream: Readable, fileName: string, mode: number, targetPath: string, options: IOptions): TPromise<void> {
const dirName = path.dirname(fileName);
const targetDirName = path.join(targetPath, dirName);
@@ -74,13 +109,18 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions): TP
last = throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options)));
});
});
}).then(null, err => TPromise.wrapError(toExtractError(err)));
}
function openZip(zipFile: string): TPromise<ZipFile> {
return nfcall<ZipFile>(_openZip, zipFile)
.then(null, err => TPromise.wrapError(toExtractError(err)));
}
export function extract(zipPath: string, targetPath: string, options: IExtractOptions = {}): TPromise<void> {
const sourcePathRegex = new RegExp(options.sourcePath ? `^${options.sourcePath}` : '');
let promise = nfcall<ZipFile>(openZip, zipPath);
let promise = openZip(zipPath);
if (options.overwrite) {
promise = promise.then(zipfile => rimraf(targetPath).then(() => zipfile));
@@ -90,7 +130,7 @@ export function extract(zipPath: string, targetPath: string, options: IExtractOp
}
function read(zipPath: string, filePath: string): TPromise<Readable> {
return nfcall(openZip, zipPath).then((zipfile: ZipFile) => {
return openZip(zipPath).then(zipfile => {
return new TPromise<Readable>((c, e) => {
zipfile.on('entry', (entry: Entry) => {
if (entry.fileName === filePath) {