bootstrap.js 7.5 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6 7 8
//@ts-check
'use strict';

9 10 11 12 13 14 15
//#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)
16
// @ts-ignore
17 18 19 20 21 22
process.on('SIGPIPE', () => {
	console.error(new Error('Unexpected SIGPIPE'));
});

//#endregion

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
//#region Add support for redirecting the loading of node modules
exports.injectNodeModuleLookupPath = function (injectPath) {
	if (!injectPath) {
		throw new Error('Missing injectPath');
	}

	// @ts-ignore
	const Module = require('module');
	const path = require('path');

	const nodeModulesPath = path.join(__dirname, '../node_modules');

	// @ts-ignore
	const originalResolveLookupPaths = Module._resolveLookupPaths;

	// @ts-ignore
	Module._resolveLookupPaths = function (moduleName, parent, newReturn) {
		const result = originalResolveLookupPaths(moduleName, parent, newReturn);

		const paths = newReturn ? result : result[1];
		for (let i = 0, len = paths.length; i < len; i++) {
			if (paths[i] === nodeModulesPath) {
				paths.splice(i, 0, injectPath);
				break;
			}
		}

		return result;
	};
};
//#endregion

A
Alex Dima 已提交
55
//#region Add support for using node_modules.asar
B
Benjamin Pasero 已提交
56 57 58 59
/**
 * @param {string=} nodeModulesPath
 */
exports.enableASARSupport = function (nodeModulesPath) {
60

61
	// @ts-ignore
A
Alex Dima 已提交
62
	const Module = require('module');
63
	const path = require('path');
64

B
Benjamin Pasero 已提交
65 66 67 68 69
	let NODE_MODULES_PATH = nodeModulesPath;
	if (!NODE_MODULES_PATH) {
		NODE_MODULES_PATH = path.join(__dirname, '../node_modules');
	}

A
Alex Dima 已提交
70 71
	const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar';

72
	// @ts-ignore
A
Alex Dima 已提交
73
	const originalResolveLookupPaths = Module._resolveLookupPaths;
74
	// @ts-ignore
A
Alex Dima 已提交
75 76
	Module._resolveLookupPaths = function (request, parent, newReturn) {
		const result = originalResolveLookupPaths(request, parent, newReturn);
A
Alex Dima 已提交
77

A
Alex Dima 已提交
78
		const paths = newReturn ? result : result[1];
A
Alex Dima 已提交
79 80 81 82 83 84 85 86 87
		for (let i = 0, len = paths.length; i < len; i++) {
			if (paths[i] === NODE_MODULES_PATH) {
				paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
				break;
			}
		}

		return result;
	};
88
};
A
Alex Dima 已提交
89
//#endregion
90

91
//#region URI helpers
92 93 94 95
/**
 * @param {string} _path
 * @returns {string}
 */
96 97
exports.uriFromPath = function (_path) {
	const path = require('path');
98

99 100 101 102
	let pathName = path.resolve(_path).replace(/\\/g, '/');
	if (pathName.length > 0 && pathName.charAt(0) !== '/') {
		pathName = '/' + pathName;
	}
103

104 105
	/** @type {string} */
	let uri;
B
Benjamin Pasero 已提交
106
	if (process.platform === 'win32' && pathName.startsWith('//')) { // specially handle Windows UNC paths
107 108 109 110 111 112
		uri = encodeURI('file:' + pathName);
	} else {
		uri = encodeURI('file://' + pathName);
	}

	return uri.replace(/#/g, '%23');
113 114
};
//#endregion
E
Erich Gamma 已提交
115

116
//#region FS helpers
117 118
/**
 * @param {string} file
119
 * @returns {Promise<string>}
120
 */
121 122
exports.readFile = function (file) {
	const fs = require('fs');
E
Erich Gamma 已提交
123

124 125 126 127 128 129 130 131 132 133
	return new Promise(function (resolve, reject) {
		fs.readFile(file, 'utf8', function (err, data) {
			if (err) {
				reject(err);
				return;
			}
			resolve(data);
		});
	});
};
E
Erich Gamma 已提交
134

135 136 137
/**
 * @param {string} file
 * @param {string} content
138
 * @returns {Promise<void>}
139
 */
140 141
exports.writeFile = function (file, content) {
	const fs = require('fs');
E
Erich Gamma 已提交
142

143 144 145 146 147 148 149 150 151 152
	return new Promise(function (resolve, reject) {
		fs.writeFile(file, content, 'utf8', function (err) {
			if (err) {
				reject(err);
				return;
			}
			resolve();
		});
	});
};
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

/**
 * @param {string} dir
 * @returns {Promise<string>}
 */
function mkdir(dir) {
	const fs = require('fs');

	return new Promise((c, e) => fs.mkdir(dir, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
}

/**
 * @param {string} dir
 * @returns {Promise<string>}
 */
exports.mkdirp = function mkdirp(dir) {
	const path = require('path');

	return mkdir(dir).then(null, err => {
		if (err && err.code === 'ENOENT') {
			const parent = path.dirname(dir);

			if (parent !== dir) { // if not arrived at root
				return mkdirp(parent).then(() => mkdir(dir));
			}
		}

		throw err;
	});
};
183
//#endregion
E
Erich Gamma 已提交
184

185
//#region NLS helpers
186 187 188
/**
 * @returns {{locale?: string, availableLanguages: {[lang: string]: string;}, pseudo?: boolean }}
 */
189 190
exports.setupNLS = function () {
	const path = require('path');
E
Erich Gamma 已提交
191

192 193 194
	// Get the nls configuration into the process.env as early as possible.
	let nlsConfig = { availableLanguages: {} };
	if (process.env['VSCODE_NLS_CONFIG']) {
195
		try {
196 197 198
			nlsConfig = JSON.parse(process.env['VSCODE_NLS_CONFIG']);
		} catch (e) {
			// Ignore
199 200 201
		}
	}

202 203
	if (nlsConfig._resolvedLanguagePackCoreLocation) {
		const bundles = Object.create(null);
204

205
		nlsConfig.loadBundle = function (bundle, language, cb) {
M
Max Belsky 已提交
206
			const result = bundles[bundle];
207 208 209 210 211 212 213 214
			if (result) {
				cb(undefined, result);

				return;
			}

			const bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json');
			exports.readFile(bundleFile).then(function (content) {
M
Max Belsky 已提交
215
				const json = JSON.parse(content);
216 217 218 219 220 221 222 223 224 225 226 227 228
				bundles[bundle] = json;

				cb(undefined, json);
			}).catch((error) => {
				try {
					if (nlsConfig._corruptedFile) {
						exports.writeFile(nlsConfig._corruptedFile, 'corrupted').catch(function (error) { console.error(error); });
					}
				} finally {
					cb(error, undefined);
				}
			});
		};
E
Erich Gamma 已提交
229
	}
230

231 232 233
	return nlsConfig;
};
//#endregion
E
Erich Gamma 已提交
234

235
//#region Portable helpers
236 237 238
/**
 * @returns {{ portableDataPath: string, isPortable: boolean }}
 */
239
exports.configurePortable = function () {
240 241
	// @ts-ignore
	const product = require('../product.json');
242 243
	const path = require('path');
	const fs = require('fs');
244

245
	const appRoot = path.dirname(__dirname);
J
Joao Moreno 已提交
246

247 248 249 250
	function getApplicationPath() {
		if (process.env['VSCODE_DEV']) {
			return appRoot;
		}
251

252 253 254
		if (process.platform === 'darwin') {
			return path.dirname(path.dirname(path.dirname(appRoot)));
		}
255

256
		return path.dirname(path.dirname(appRoot));
J
Joao Moreno 已提交
257
	}
258 259 260 261 262 263 264 265

	function getPortableDataPath() {
		if (process.env['VSCODE_PORTABLE']) {
			return process.env['VSCODE_PORTABLE'];
		}

		if (process.platform === 'win32' || process.platform === 'linux') {
			return path.join(getApplicationPath(), 'data');
266
		}
267 268 269

		const portableDataName = product.portable || `${product.applicationName}-portable-data`;
		return path.join(path.dirname(getApplicationPath()), portableDataName);
270 271
	}

272
	const portableDataPath = getPortableDataPath();
J
Joao Moreno 已提交
273
	const isPortable = !('target' in product) && fs.existsSync(portableDataPath);
274 275 276 277 278 279 280 281 282 283 284 285
	const portableTempPath = path.join(portableDataPath, 'tmp');
	const isTempPortable = isPortable && fs.existsSync(portableTempPath);

	if (isPortable) {
		process.env['VSCODE_PORTABLE'] = portableDataPath;
	} else {
		delete process.env['VSCODE_PORTABLE'];
	}

	if (isTempPortable) {
		process.env[process.platform === 'win32' ? 'TEMP' : 'TMPDIR'] = portableTempPath;
	}
286

287 288 289 290 291
	return {
		portableDataPath,
		isPortable
	};
};
R
Ramya Rao 已提交
292 293 294 295 296 297 298 299
//#endregion

//#region ApplicationInsights
/**
 * Prevents appinsights from monkey patching modules.
 * This should be called before importing the applicationinsights module
 */
exports.avoidMonkeyPatchFromAppInsights = function () {
300
	// @ts-ignore
R
Ramya Rao 已提交
301 302 303
	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
};
M
Max Belsky 已提交
304
//#endregion