mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from master
This commit is contained in:
310
src/bootstrap.js
vendored
310
src/bootstrap.js
vendored
@@ -3,14 +3,43 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
//#region global bootstrapping
|
||||
|
||||
// increase number of stack frames(from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)
|
||||
Error.stackTraceLimit = 100;
|
||||
|
||||
// Workaround for Electron not installing a handler to ignore SIGPIPE
|
||||
// (https://github.com/electron/electron/issues/13254)
|
||||
// @ts-ignore
|
||||
process.on('SIGPIPE', () => {
|
||||
console.error(new Error('Unexpected SIGPIPE'));
|
||||
});
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Add support for using node_modules.asar
|
||||
(function () {
|
||||
const path = require('path');
|
||||
/**
|
||||
* @param {string=} nodeModulesPath
|
||||
*/
|
||||
exports.enableASARSupport = function (nodeModulesPath) {
|
||||
|
||||
// @ts-ignore
|
||||
const Module = require('module');
|
||||
const NODE_MODULES_PATH = path.join(__dirname, '../node_modules');
|
||||
const path = require('path');
|
||||
|
||||
let NODE_MODULES_PATH = nodeModulesPath;
|
||||
if (!NODE_MODULES_PATH) {
|
||||
NODE_MODULES_PATH = path.join(__dirname, '../node_modules');
|
||||
}
|
||||
|
||||
const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar';
|
||||
|
||||
// @ts-ignore
|
||||
const originalResolveLookupPaths = Module._resolveLookupPaths;
|
||||
// @ts-ignore
|
||||
Module._resolveLookupPaths = function (request, parent, newReturn) {
|
||||
const result = originalResolveLookupPaths(request, parent, newReturn);
|
||||
|
||||
@@ -24,149 +53,182 @@
|
||||
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
};
|
||||
//#endregion
|
||||
|
||||
// Will be defined if we got forked from another node process
|
||||
// In that case we override console.log/warn/error to be able
|
||||
// to send loading issues to the main side for logging.
|
||||
if (!!process.send && process.env.PIPE_LOGGING === 'true') {
|
||||
var MAX_LENGTH = 100000;
|
||||
//#region URI helpers
|
||||
/**
|
||||
* @param {string} _path
|
||||
* @returns {string}
|
||||
*/
|
||||
exports.uriFromPath = function (_path) {
|
||||
const path = require('path');
|
||||
|
||||
// Prevent circular stringify and convert arguments to real array
|
||||
function safeToArray(args) {
|
||||
var seen = [];
|
||||
var res;
|
||||
var argsArray = [];
|
||||
let pathName = path.resolve(_path).replace(/\\/g, '/');
|
||||
if (pathName.length > 0 && pathName.charAt(0) !== '/') {
|
||||
pathName = '/' + pathName;
|
||||
}
|
||||
|
||||
// Massage some arguments with special treatment
|
||||
if (args.length) {
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
return encodeURI('file://' + pathName).replace(/#/g, '%23');
|
||||
};
|
||||
//#endregion
|
||||
|
||||
// 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';
|
||||
}
|
||||
//#region FS helpers
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
exports.readFile = function (file) {
|
||||
const fs = require('fs');
|
||||
|
||||
// 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) {
|
||||
var errorObj = args[i];
|
||||
if (errorObj.stack) {
|
||||
args[i] = errorObj.stack;
|
||||
} else {
|
||||
args[i] = errorObj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
argsArray.push(args[i]);
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.readFile(file, 'utf8', function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 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;
|
||||
argsArray.push({ __$stack: stack.split('\n').slice(3).join('\n') });
|
||||
}
|
||||
/**
|
||||
* @param {string} file
|
||||
* @param {string} content
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.writeFile = function (file, content) {
|
||||
const fs = require('fs');
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.writeFile(file, content, 'utf8', function (err) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//#region NLS helpers
|
||||
/**
|
||||
* @returns {{locale?: string, availableLanguages: {[lang: string]: string;}, pseudo?: boolean }}
|
||||
*/
|
||||
exports.setupNLS = function () {
|
||||
const path = require('path');
|
||||
|
||||
// Get the nls configuration into the process.env as early as possible.
|
||||
let nlsConfig = { availableLanguages: {} };
|
||||
if (process.env['VSCODE_NLS_CONFIG']) {
|
||||
try {
|
||||
res = JSON.stringify(argsArray, function (key, value) {
|
||||
nlsConfig = JSON.parse(process.env['VSCODE_NLS_CONFIG']);
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Objects get special treatment to prevent circles
|
||||
if (value && Object.prototype.toString.call(value) === '[object Object]') {
|
||||
if (seen.indexOf(value) !== -1) {
|
||||
return Object.create(null); // prevent circular references!
|
||||
if (nlsConfig._resolvedLanguagePackCoreLocation) {
|
||||
const bundles = Object.create(null);
|
||||
|
||||
nlsConfig.loadBundle = function (bundle, language, cb) {
|
||||
let result = bundles[bundle];
|
||||
if (result) {
|
||||
cb(undefined, result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json');
|
||||
exports.readFile(bundleFile).then(function (content) {
|
||||
let json = JSON.parse(content);
|
||||
bundles[bundle] = json;
|
||||
|
||||
cb(undefined, json);
|
||||
}).catch((error) => {
|
||||
try {
|
||||
if (nlsConfig._corruptedFile) {
|
||||
exports.writeFile(nlsConfig._corruptedFile, 'corrupted').catch(function (error) { console.error(error); });
|
||||
}
|
||||
|
||||
seen.push(value);
|
||||
} finally {
|
||||
cb(error, undefined);
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
} catch (error) {
|
||||
return 'Output omitted for an object that cannot be inspected (' + error.toString() + ')';
|
||||
}
|
||||
|
||||
if (res && res.length > MAX_LENGTH) {
|
||||
return 'Output omitted for a large object that exceeds the limits';
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
function safeSend(arg) {
|
||||
try {
|
||||
process.send(arg);
|
||||
} catch (error) {
|
||||
// Can happen if the parent channel is closed meanwhile
|
||||
return nlsConfig;
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//#region Portable helpers
|
||||
/**
|
||||
* @returns {{ portableDataPath: string, isPortable: boolean }}
|
||||
*/
|
||||
exports.configurePortable = function () {
|
||||
// @ts-ignore
|
||||
const product = require('../product.json');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const appRoot = path.dirname(__dirname);
|
||||
|
||||
function getApplicationPath() {
|
||||
if (process.env['VSCODE_DEV']) {
|
||||
return appRoot;
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
return path.dirname(path.dirname(path.dirname(appRoot)));
|
||||
}
|
||||
|
||||
return path.dirname(path.dirname(appRoot));
|
||||
}
|
||||
|
||||
// Pass console logging to the outside so that we have it in the main side if told so
|
||||
if (process.env.VERBOSE_LOGGING === 'true') {
|
||||
console.log = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); };
|
||||
console.info = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); };
|
||||
console.warn = function () { safeSend({ type: '__$console', severity: 'warn', arguments: safeToArray(arguments) }); };
|
||||
function getPortableDataPath() {
|
||||
if (process.env['VSCODE_PORTABLE']) {
|
||||
return process.env['VSCODE_PORTABLE'];
|
||||
}
|
||||
|
||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
||||
return path.join(getApplicationPath(), 'data');
|
||||
}
|
||||
|
||||
const portableDataName = product.portable || `${product.applicationName}-portable-data`;
|
||||
return path.join(path.dirname(getApplicationPath()), portableDataName);
|
||||
}
|
||||
|
||||
const portableDataPath = getPortableDataPath();
|
||||
const isPortable = !('target' in product) && fs.existsSync(portableDataPath);
|
||||
const portableTempPath = path.join(portableDataPath, 'tmp');
|
||||
const isTempPortable = isPortable && fs.existsSync(portableTempPath);
|
||||
|
||||
if (isPortable) {
|
||||
process.env['VSCODE_PORTABLE'] = portableDataPath;
|
||||
} else {
|
||||
console.log = function () { /* ignore */ };
|
||||
console.warn = function () { /* ignore */ };
|
||||
console.info = function () { /* ignore */ };
|
||||
delete process.env['VSCODE_PORTABLE'];
|
||||
}
|
||||
|
||||
console.error = function () { safeSend({ type: '__$console', severity: 'error', arguments: safeToArray(arguments) }); };
|
||||
}
|
||||
|
||||
if (!process.env['VSCODE_ALLOW_IO']) {
|
||||
// Let stdout, stderr and stdin be no-op streams. This prevents an issue where we would get an EBADF
|
||||
// error when we are inside a forked process and this process tries to access those channels.
|
||||
var stream = require('stream');
|
||||
var writable = new stream.Writable({
|
||||
write: function () { /* No OP */ }
|
||||
});
|
||||
|
||||
process.__defineGetter__('stdout', function () { return writable; });
|
||||
process.__defineGetter__('stderr', function () { return writable; });
|
||||
process.__defineGetter__('stdin', function () { return writable; });
|
||||
}
|
||||
|
||||
if (!process.env['VSCODE_HANDLES_UNCAUGHT_ERRORS']) {
|
||||
// Handle uncaught exceptions
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.error('Uncaught Exception: ', err.toString());
|
||||
if (err.stack) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Kill oneself if one's parent dies. Much drama.
|
||||
if (process.env['VSCODE_PARENT_PID']) {
|
||||
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);
|
||||
if (isTempPortable) {
|
||||
process.env[process.platform === 'win32' ? 'TEMP' : 'TMPDIR'] = portableTempPath;
|
||||
}
|
||||
}
|
||||
|
||||
const crashReporterOptionsRaw = process.env['CRASH_REPORTER_START_OPTIONS'];
|
||||
if (typeof crashReporterOptionsRaw === 'string') {
|
||||
try {
|
||||
const crashReporterOptions = JSON.parse(crashReporterOptionsRaw);
|
||||
if (crashReporterOptions) {
|
||||
process.crashReporter.start(crashReporterOptions);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
return {
|
||||
portableDataPath,
|
||||
isPortable
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
|
||||
require('./bootstrap-amd').bootstrap(process.env['AMD_ENTRYPOINT']);
|
||||
//#region ApplicationInsights
|
||||
/**
|
||||
* Prevents appinsights from monkey patching modules.
|
||||
* This should be called before importing the applicationinsights module
|
||||
*/
|
||||
exports.avoidMonkeyPatchFromAppInsights = function () {
|
||||
// @ts-ignore
|
||||
process.env['APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL'] = true; // Skip monkey patching of 3rd party modules by appinsights
|
||||
global['diagnosticsSource'] = {}; // Prevents diagnostic channel (which patches "require") from initializing entirely
|
||||
};
|
||||
//#endregion
|
||||
Reference in New Issue
Block a user