index.js 11.3 KB
Newer Older
J
Joao Moreno 已提交
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.
 *--------------------------------------------------------------------------------------------*/

J
Joao Moreno 已提交
6 7
// Warning: Do not use the `let` declarator in this file, it breaks our minification

J
Joao Moreno 已提交
8 9
'use strict';

10
/*global window,document,define*/
J
Joao Moreno 已提交
11

12 13 14
const perf = require('../../../base/common/performance');
perf.mark('renderer/started');

J
Joao Moreno 已提交
15
const path = require('path');
D
Dirk Baeumer 已提交
16
const fs = require('fs');
J
Joao Moreno 已提交
17 18 19 20
const electron = require('electron');
const remote = electron.remote;
const ipc = electron.ipcRenderer;

J
Johannes Rieken 已提交
21
process.lazyEnv = new Promise(function (resolve) {
J
Joao Moreno 已提交
22 23
	const handle = setTimeout(function () {
		resolve();
J
Joao Moreno 已提交
24
		console.warn('renderer did not receive lazyEnv in time');
J
Joao Moreno 已提交
25
	}, 10000);
26
	ipc.once('vscode:acceptShellEnv', function (event, shellEnv) {
J
Joao Moreno 已提交
27
		clearTimeout(handle);
28 29 30
		assign(process.env, shellEnv);
		resolve(process.env);
	});
31
	ipc.send('vscode:fetchShellEnv');
32 33
});

B
Benjamin Pasero 已提交
34 35
Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)

J
Joao Moreno 已提交
36 37
function onError(error, enableDeveloperTools) {
	if (enableDeveloperTools) {
J
Joao Moreno 已提交
38
		remote.getCurrentWebContents().openDevTools();
J
Joao Moreno 已提交
39 40 41 42 43 44 45 46 47 48 49
	}

	console.error('[uncaught exception]: ' + error);

	if (error.stack) {
		console.error(error.stack);
	}
}

function assign(destination, source) {
	return Object.keys(source)
J
Joao Moreno 已提交
50
		.reduce(function (r, key) { r[key] = source[key]; return r; }, destination);
J
Joao Moreno 已提交
51 52 53 54 55 56
}

function parseURLQueryArgs() {
	const search = window.location.search || '';

	return search.split(/[?&]/)
J
Joao Moreno 已提交
57 58 59 60
		.filter(function (param) { return !!param; })
		.map(function (param) { return param.split('='); })
		.filter(function (param) { return param.length === 2; })
		.reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {});
J
Joao Moreno 已提交
61 62 63
}

function uriFromPath(_path) {
J
Joao Moreno 已提交
64
	var pathName = path.resolve(_path).replace(/\\/g, '/');
J
Joao Moreno 已提交
65 66 67 68 69 70 71
	if (pathName.length > 0 && pathName.charAt(0) !== '/') {
		pathName = '/' + pathName;
	}

	return encodeURI('file://' + pathName);
}

D
Dirk Baeumer 已提交
72
function readFile(file) {
73 74
	return new Promise(function (resolve, reject) {
		fs.readFile(file, 'utf8', function (err, data) {
D
Dirk Baeumer 已提交
75 76 77 78 79 80 81 82 83
			if (err) {
				reject(err);
				return;
			}
			resolve(data);
		});
	});
}

84
function showPartsSplash(configuration) {
J
Johannes Rieken 已提交
85
	perf.mark('willShowPartsSplash');
86

87 88 89 90 91
	// TODO@Ben remove me after a while
	perf.mark('willAccessLocalStorage');
	let storage = window.localStorage;
	perf.mark('didAccessLocalStorage');

J
Johannes Rieken 已提交
92 93 94 95 96 97
	let data;
	try {
		let raw = storage.getItem('storage://global/parts-splash-data');
		data = JSON.parse(raw);
	} catch (e) {
		// ignore
98
	}
J
Johannes Rieken 已提交
99

100 101 102 103 104 105 106 107
	// high contrast mode has been turned on, ignore stored colors and layouts
	if (data && configuration.highContrast && data.baseTheme !== 'hc-black') {
		data = void 0;
	}

	const style = document.createElement('style');
	document.head.appendChild(style);

J
Johannes Rieken 已提交
108
	if (data) {
109 110 111 112 113 114 115
		const { layoutInfo, colorInfo, baseTheme } = data;

		// set the theme base id used by images and some styles
		document.body.className = `monaco-shell ${baseTheme}`;
		// stylesheet that defines foreground and background color
		style.innerHTML = `.monaco-shell { background-color: ${colorInfo.editorBackground}; color: ${colorInfo.foreground}; }`;

J
Johannes Rieken 已提交
116
		const splash = document.createElement('div');
117
		splash.id = data.id;
118 119 120 121

		// ensure there is enough space
		layoutInfo.sideBarWidth = Math.min(layoutInfo.sideBarWidth, window.innerWidth - (layoutInfo.activityBarWidth + layoutInfo.editorPartMinWidth));

J
Johannes Rieken 已提交
122 123
		if (configuration.folderUri || configuration.workspace) {
			// folder or workspace -> status bar color, sidebar
124
			splash.innerHTML = `
J
Johannes Rieken 已提交
125 126 127 128
			<div style="position: absolute; width: 100%; left: 0; top: 0; height: ${layoutInfo.titleBarHeight}px; background-color: ${colorInfo.titleBarBackground};"></div>
			<div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: 0; width: ${layoutInfo.activityBarWidth}px; background-color: ${colorInfo.activityBarBackground};"></div>
			<div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: ${layoutInfo.activityBarWidth}px; width: ${layoutInfo.sideBarWidth}px; background-color: ${colorInfo.sideBarBackground};"></div>
			<div style="position: absolute; width: 100%; bottom: 0; left: 0; height: ${layoutInfo.statusBarHeight}px; background-color: ${colorInfo.statusBarBackground};"></div>
129
			`;
J
Johannes Rieken 已提交
130 131
		} else {
			// empty -> speical status bar color, no sidebar
132
			splash.innerHTML = `
J
Johannes Rieken 已提交
133 134 135
			<div style="position: absolute; width: 100%; left: 0; top: 0; height: ${layoutInfo.titleBarHeight}px; background-color: ${colorInfo.titleBarBackground};"></div>
			<div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: 0; width: ${layoutInfo.activityBarWidth}px; background-color: ${colorInfo.activityBarBackground};"></div>
			<div style="position: absolute; width: 100%; bottom: 0; left: 0; height: ${layoutInfo.statusBarHeight}px; background-color: ${colorInfo.statusBarNoFolderBackground};"></div>
136
			`;
J
Johannes Rieken 已提交
137 138
		}
		document.body.appendChild(splash);
139 140 141
	} else {
		document.body.className = `monaco-shell ${configuration.highContrast ? 'hc-black' : 'vs-dark'}`;
		style.innerHTML = `.monaco-shell { background-color: ${configuration.highContrast ? '#000000' : '#1E1E1E'}; color: ${configuration.highContrast ? '#FFFFFF' : '#CCCCCC'}; }`;
142
	}
143

J
Johannes Rieken 已提交
144
	perf.mark('didShowPartsSplash');
145 146
}

147 148
const writeFile = (file, content) => new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));

J
Joao Moreno 已提交
149 150 151
function registerListeners(enableDeveloperTools) {

	// Devtools & reload support
B
Benjamin Pasero 已提交
152
	var listener;
J
Joao Moreno 已提交
153
	if (enableDeveloperTools) {
154
		const extractKey = function (e) {
J
Joao Moreno 已提交
155 156 157 158 159 160 161 162 163 164 165 166
			return [
				e.ctrlKey ? 'ctrl-' : '',
				e.metaKey ? 'meta-' : '',
				e.altKey ? 'alt-' : '',
				e.shiftKey ? 'shift-' : '',
				e.keyCode
			].join('');
		};

		const TOGGLE_DEV_TOOLS_KB = (process.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I
		const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R

B
Benjamin Pasero 已提交
167
		listener = function (e) {
J
Joao Moreno 已提交
168 169
			const key = extractKey(e);
			if (key === TOGGLE_DEV_TOOLS_KB) {
J
Joao Moreno 已提交
170
				remote.getCurrentWebContents().toggleDevTools();
J
Joao Moreno 已提交
171
			} else if (key === RELOAD_KB) {
172
				remote.getCurrentWindow().reload();
J
Joao Moreno 已提交
173
			}
B
Benjamin Pasero 已提交
174 175
		};
		window.addEventListener('keydown', listener);
J
Joao Moreno 已提交
176 177
	}

J
Joao Moreno 已提交
178
	process.on('uncaughtException', function (error) { onError(error, enableDeveloperTools); });
B
Benjamin Pasero 已提交
179 180 181 182 183 184

	return function () {
		if (listener) {
			window.removeEventListener('keydown', listener);
			listener = void 0;
		}
J
Joao Moreno 已提交
185
	};
J
Joao Moreno 已提交
186 187 188 189 190 191 192
}

function main() {
	const webFrame = require('electron').webFrame;
	const args = parseURLQueryArgs();
	const configuration = JSON.parse(args['config'] || '{}') || {};

A
Alex Dima 已提交
193 194 195 196 197 198 199 200 201 202 203 204
	//#region Add support for using node_modules.asar
	(function () {
		const path = require('path');
		const Module = require('module');
		let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules');
		if (/[a-z]\:/.test(NODE_MODULES_PATH)) {
			// Make drive letter uppercase
			NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1);
		}
		const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar';

		const originalResolveLookupPaths = Module._resolveLookupPaths;
A
Alex Dima 已提交
205 206
		Module._resolveLookupPaths = function (request, parent, newReturn) {
			const result = originalResolveLookupPaths(request, parent, newReturn);
A
Alex Dima 已提交
207

A
Alex Dima 已提交
208
			const paths = newReturn ? result : result[1];
A
Alex Dima 已提交
209 210 211 212 213 214 215 216 217 218 219 220
			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;
		};
	})();
	//#endregion

J
Joao Moreno 已提交
221 222
	// Correctly inherit the parent's environment
	assign(process.env, configuration.userEnv);
223
	perf.importEntries(configuration.perfEntries);
J
Joao Moreno 已提交
224

225
	showPartsSplash(configuration);
226

J
Joao Moreno 已提交
227
	// Get the nls configuration into the process.env as early as possible.
J
Joao Moreno 已提交
228
	var nlsConfig = { availableLanguages: {} };
J
Joao Moreno 已提交
229 230 231 232 233 234 235 236
	const config = process.env['VSCODE_NLS_CONFIG'];
	if (config) {
		process.env['VSCODE_NLS_CONFIG'] = config;
		try {
			nlsConfig = JSON.parse(config);
		} catch (e) { /*noop*/ }
	}

D
Dirk Baeumer 已提交
237 238
	if (nlsConfig._resolvedLanguagePackCoreLocation) {
		let bundles = Object.create(null);
239
		nlsConfig.loadBundle = function (bundle, language, cb) {
D
Dirk Baeumer 已提交
240 241 242 243 244 245 246 247 248 249
			let result = bundles[bundle];
			if (result) {
				cb(undefined, result);
				return;
			}
			let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json');
			readFile(bundleFile).then(function (content) {
				let json = JSON.parse(content);
				bundles[bundle] = json;
				cb(undefined, json);
250 251 252 253 254 255 256 257 258
			}).catch((error) => {
				try {
					if (nlsConfig._corruptedFile) {
						writeFile(nlsConfig._corruptedFile, 'corrupted').catch(function (error) { console.error(error); });
					}
				} finally {
					cb(error, undefined);
				}
			});
D
Dirk Baeumer 已提交
259 260 261
		};
	}

J
Joao Moreno 已提交
262
	var locale = nlsConfig.availableLanguages['*'] || 'en';
J
Joao Moreno 已提交
263 264 265 266 267 268 269
	if (locale === 'zh-tw') {
		locale = 'zh-Hant';
	} else if (locale === 'zh-cn') {
		locale = 'zh-Hans';
	}
	window.document.documentElement.setAttribute('lang', locale);

270
	const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath;
B
Benjamin Pasero 已提交
271
	const unbind = registerListeners(enableDeveloperTools);
J
Joao Moreno 已提交
272

273
	// disable pinch zoom & apply zoom level early to avoid glitches
274
	const zoomLevel = configuration.zoomLevel;
275
	webFrame.setVisualZoomLevelLimits(1, 1);
276 277
	if (typeof zoomLevel === 'number' && zoomLevel !== 0) {
		webFrame.setZoomLevel(zoomLevel);
J
Joao Moreno 已提交
278 279 280
	}

	// Load the loader and start loading the workbench
281 282 283
	const loaderFilename = configuration.appRoot + '/out/vs/loader.js';
	const loaderSource = require('fs').readFileSync(loaderFilename);
	require('vm').runInThisContext(loaderSource, { filename: loaderFilename });
284 285
	var define = global.define;
	global.define = undefined;
J
Joao 已提交
286

287
	window.nodeRequire = require.__$__nodeRequire;
B
Benjamin Pasero 已提交
288

289
	define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code
290

291
	window.MonacoEnvironment = {};
J
Joao Moreno 已提交
292

293 294 295 296 297 298 299 300 301
	const onNodeCachedData = window.MonacoEnvironment.onNodeCachedData = [];
	require.config({
		baseUrl: uriFromPath(configuration.appRoot) + '/out',
		'vs/nls': nlsConfig,
		recordStats: !!configuration.performance,
		nodeCachedDataDir: configuration.nodeCachedDataDir,
		onNodeCachedData: function () { onNodeCachedData.push(arguments); },
		nodeModules: [/*BUILD->INSERT_NODE_MODULES*/]
	});
J
Joao Moreno 已提交
302

303 304 305
	if (nlsConfig.pseudo) {
		require(['vs/nls'], function (nlsPlugin) {
			nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
J
Joao Moreno 已提交
306
		});
307 308
	}

J
Johannes Rieken 已提交
309
	perf.mark('willLoadWorkbenchMain');
310 311 312 313 314
	require([
		'vs/workbench/workbench.main',
		'vs/nls!vs/workbench/workbench.main',
		'vs/css!vs/workbench/workbench.main'
	], function () {
J
Johannes Rieken 已提交
315
		perf.mark('didLoadWorkbenchMain');
316 317 318 319 320 321 322 323 324 325 326 327

		process.lazyEnv.then(function () {
			perf.mark('main/startup');
			require('vs/workbench/electron-browser/main')
				.startup(configuration)
				.done(function () {
					unbind(); // since the workbench is running, unbind our developer related listeners and let the workbench handle them
				}, function (error) {
					onError(error, enableDeveloperTools);
				});
		});
	});
328

J
Joao Moreno 已提交
329 330
}

331
main();