eae5d8c807
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
226 lines
6.3 KiB
JavaScript
226 lines
6.3 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
//@ts-check
|
|
'use strict';
|
|
|
|
const performance = require('./vs/base/common/performance');
|
|
performance.mark('code/fork/start');
|
|
|
|
const bootstrap = require('./bootstrap');
|
|
const bootstrapNode = require('./bootstrap-node');
|
|
|
|
// Remove global paths from the node module lookup
|
|
bootstrapNode.removeGlobalNodeModuleLookupPaths();
|
|
|
|
// Enable ASAR in our forked processes
|
|
bootstrap.enableASARSupport(undefined);
|
|
|
|
if (process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']) {
|
|
bootstrapNode.injectNodeModuleLookupPath(process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']);
|
|
}
|
|
|
|
// Configure: pipe logging to parent process
|
|
if (!!process.send && process.env['VSCODE_PIPE_LOGGING'] === 'true') {
|
|
pipeLoggingToParent();
|
|
}
|
|
|
|
// Handle Exceptions
|
|
if (!process.env['VSCODE_HANDLES_UNCAUGHT_ERRORS']) {
|
|
handleExceptions();
|
|
}
|
|
|
|
// Terminate when parent terminates
|
|
if (process.env['VSCODE_PARENT_PID']) {
|
|
terminateWhenParentTerminates();
|
|
}
|
|
|
|
// Configure Crash Reporter
|
|
configureCrashReporter();
|
|
|
|
// Load AMD entry point
|
|
require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
|
|
|
|
|
|
//#region Helpers
|
|
|
|
function pipeLoggingToParent() {
|
|
const MAX_LENGTH = 100000;
|
|
|
|
// Prevent circular stringify and convert arguments to real array
|
|
function safeToArray(args) {
|
|
const seen = [];
|
|
const argsArray = [];
|
|
|
|
// Massage some arguments with special treatment
|
|
if (args.length) {
|
|
for (let i = 0; i < args.length; i++) {
|
|
|
|
// Any argument of type 'undefined' needs to be specially treated because
|
|
// JSON.stringify will simply ignore those. We replace them with the string
|
|
// 'undefined' which is not 100% right, but good enough to be logged to console
|
|
if (typeof args[i] === 'undefined') {
|
|
args[i] = 'undefined';
|
|
}
|
|
|
|
// Any argument that is an Error will be changed to be just the error stack/message
|
|
// itself because currently cannot serialize the error over entirely.
|
|
else if (args[i] instanceof Error) {
|
|
const errorObj = args[i];
|
|
if (errorObj.stack) {
|
|
args[i] = errorObj.stack;
|
|
} else {
|
|
args[i] = errorObj.toString();
|
|
}
|
|
}
|
|
|
|
argsArray.push(args[i]);
|
|
}
|
|
}
|
|
|
|
// Add the stack trace as payload if we are told so. We remove the message and the 2 top frames
|
|
// to start the stacktrace where the console message was being written
|
|
if (process.env['VSCODE_LOG_STACK'] === 'true') {
|
|
const stack = new Error().stack;
|
|
if (stack) {
|
|
argsArray.push({ __$stack: stack.split('\n').slice(3).join('\n') });
|
|
}
|
|
}
|
|
|
|
try {
|
|
const res = JSON.stringify(argsArray, function (key, value) {
|
|
|
|
// Objects get special treatment to prevent circles
|
|
if (isObject(value) || Array.isArray(value)) {
|
|
if (seen.indexOf(value) !== -1) {
|
|
return '[Circular]';
|
|
}
|
|
|
|
seen.push(value);
|
|
}
|
|
|
|
return value;
|
|
});
|
|
|
|
if (res.length > MAX_LENGTH) {
|
|
return 'Output omitted for a large object that exceeds the limits';
|
|
}
|
|
|
|
return res;
|
|
} catch (error) {
|
|
return `Output omitted for an object that cannot be inspected ('${error.toString()}')`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {{ type: string; severity: string; arguments: string; }} arg
|
|
*/
|
|
function safeSend(arg) {
|
|
try {
|
|
if (process.send) {
|
|
process.send(arg);
|
|
}
|
|
} catch (error) {
|
|
// Can happen if the parent channel is closed meanwhile
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} obj
|
|
*/
|
|
function isObject(obj) {
|
|
return typeof obj === 'object'
|
|
&& obj !== null
|
|
&& !Array.isArray(obj)
|
|
&& !(obj instanceof RegExp)
|
|
&& !(obj instanceof Date);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {'log' | 'warn' | 'error'} severity
|
|
* @param {string} args
|
|
*/
|
|
function safeSendConsoleMessage(severity, args) {
|
|
safeSend({ type: '__$console', severity, arguments: args });
|
|
}
|
|
|
|
/**
|
|
* @param {'log' | 'info' | 'warn' | 'error'} method
|
|
* @param {'log' | 'warn' | 'error'} severity
|
|
*/
|
|
function wrapConsoleMethod(method, severity) {
|
|
if (process.env['VSCODE_LOG_NATIVE'] === 'true') {
|
|
const original = console[method];
|
|
console[method] = function () {
|
|
safeSendConsoleMessage(severity, safeToArray(arguments));
|
|
|
|
const stream = method === 'error' || method === 'warn' ? process.stderr : process.stdout;
|
|
stream.write('\nSTART_NATIVE_LOG\n');
|
|
original.apply(console, arguments);
|
|
stream.write('\nEND_NATIVE_LOG\n');
|
|
};
|
|
} else {
|
|
console[method] = function () { safeSendConsoleMessage(severity, safeToArray(arguments)); };
|
|
}
|
|
}
|
|
|
|
// Pass console logging to the outside so that we have it in the main side if told so
|
|
if (process.env['VSCODE_VERBOSE_LOGGING'] === 'true') {
|
|
wrapConsoleMethod('info', 'log');
|
|
wrapConsoleMethod('log', 'log');
|
|
wrapConsoleMethod('warn', 'warn');
|
|
wrapConsoleMethod('error', 'error');
|
|
} else if (process.env['VSCODE_LOG_NATIVE'] !== 'true') {
|
|
console.log = function () { /* ignore */ };
|
|
console.warn = function () { /* ignore */ };
|
|
console.info = function () { /* ignore */ };
|
|
wrapConsoleMethod('error', 'error');
|
|
}
|
|
}
|
|
|
|
function handleExceptions() {
|
|
|
|
// Handle uncaught exceptions
|
|
process.on('uncaughtException', function (err) {
|
|
console.error('Uncaught Exception: ', err);
|
|
});
|
|
|
|
// Handle unhandled promise rejections
|
|
process.on('unhandledRejection', function (reason) {
|
|
console.error('Unhandled Promise Rejection: ', reason);
|
|
});
|
|
}
|
|
|
|
function terminateWhenParentTerminates() {
|
|
const parentPid = Number(process.env['VSCODE_PARENT_PID']);
|
|
|
|
if (typeof parentPid === 'number' && !isNaN(parentPid)) {
|
|
setInterval(function () {
|
|
try {
|
|
process.kill(parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
|
} catch (e) {
|
|
process.exit();
|
|
}
|
|
}, 5000);
|
|
}
|
|
}
|
|
|
|
function configureCrashReporter() {
|
|
const crashReporterOptionsRaw = process.env['VSCODE_CRASH_REPORTER_START_OPTIONS'];
|
|
if (typeof crashReporterOptionsRaw === 'string') {
|
|
try {
|
|
const crashReporterOptions = JSON.parse(crashReporterOptionsRaw);
|
|
if (crashReporterOptions && process['crashReporter'] /* Electron only */) {
|
|
process['crashReporter'].start(crashReporterOptions);
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
//#endregion
|