bootstrap-window.js 6.1 KB
Newer Older
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
const bootstrap = require('./bootstrap');

11 12 13 14 15 16
/**
 * @param {object} destination
 * @param {object} source
 * @returns {object}
 */
exports.assign = function assign(destination, source) {
17 18 19
	return Object.keys(source).reduce(function (r, key) { r[key] = source[key]; return r; }, destination);
};

20 21 22
/**
 *
 * @param {string[]} modulePaths
23 24
 * @param {(result, configuration: object) => any} resultCallback
 * @param {{ forceEnableDeveloperKeybindings?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config: object) => void, beforeLoaderConfig?: (config: object, loaderConfig: object) => void, beforeRequire?: () => void }=} options
25
 */
26
exports.load = function (modulePaths, resultCallback, options) {
27

28
	// @ts-ignore
29
	const webFrame = require('electron').webFrame;
B
Benjamin Pasero 已提交
30
	const path = require('path');
31

32
	const args = parseURLQueryArgs();
33 34 35
	const configuration = JSON.parse(args['config'] || '{}') || {};

	// Error handler
36
	// @ts-ignore
37 38 39
	process.on('uncaughtException', function (error) {
		onUnexpectedError(error, enableDeveloperTools);
	});
40 41 42 43

	// Developer tools
	const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath;
	let developerToolsUnbind;
B
Benjamin Pasero 已提交
44
	if (enableDeveloperTools || (options && options.forceEnableDeveloperKeybindings)) {
45 46 47 48 49 50 51
		developerToolsUnbind = registerDeveloperKeybindings();
	}

	// Correctly inherit the parent's environment
	exports.assign(process.env, configuration.userEnv);

	// Enable ASAR support
B
Benjamin Pasero 已提交
52
	bootstrap.enableASARSupport(path.join(configuration.appRoot, 'node_modules'));
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

	// disable pinch zoom & apply zoom level early to avoid glitches
	const zoomLevel = configuration.zoomLevel;
	webFrame.setVisualZoomLevelLimits(1, 1);
	if (typeof zoomLevel === 'number' && zoomLevel !== 0) {
		webFrame.setZoomLevel(zoomLevel);
	}

	if (options && typeof options.canModifyDOM === 'function') {
		options.canModifyDOM(configuration);
	}

	// Get the nls configuration into the process.env as early as possible.
	const nlsConfig = bootstrap.setupNLS();

	let locale = nlsConfig.availableLanguages['*'] || 'en';
	if (locale === 'zh-tw') {
		locale = 'zh-Hant';
	} else if (locale === 'zh-cn') {
		locale = 'zh-Hans';
	}

	window.document.documentElement.setAttribute('lang', locale);

	// Load the loader
78 79 80 81
	const amdLoader = require(configuration.appRoot + '/out/vs/loader.js');
	const amdRequire = amdLoader.require;
	const amdDefine = amdLoader.require.define;
	const nodeRequire = amdLoader.require.nodeRequire;
82

83 84
	window['nodeRequire'] = nodeRequire;
	window['require'] = amdRequire;
85

86 87
	// replace the patched electron fs with the original node fs for all AMD code
	amdDefine('fs', ['original-fs'], function (originalFS) { return originalFS; });
88

89
	window['MonacoEnvironment'] = {};
90

91 92 93 94 95
	const loaderConfig = {
		baseUrl: bootstrap.uriFromPath(configuration.appRoot) + '/out',
		'vs/nls': nlsConfig,
		nodeModules: [/*BUILD->INSERT_NODE_MODULES*/]
	};
96

97 98 99 100 101 102 103 104
	// cached data config
	if (configuration.nodeCachedDataDir) {
		loaderConfig.nodeCachedData = {
			path: configuration.nodeCachedDataDir,
			seed: modulePaths.join('')
		};
	}

105 106 107
	if (options && typeof options.beforeLoaderConfig === 'function') {
		options.beforeLoaderConfig(configuration, loaderConfig);
	}
108

109
	amdRequire.config(loaderConfig);
110

111 112 113 114 115
	if (nlsConfig.pseudo) {
		amdRequire(['vs/nls'], function (nlsPlugin) {
			nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
		});
	}
116

117 118 119
	if (options && typeof options.beforeRequire === 'function') {
		options.beforeRequire();
	}
120

121 122 123 124 125
	amdRequire(modulePaths, result => {
		try {
			const callbackResult = resultCallback(result, configuration);
			if (callbackResult && typeof callbackResult.then === 'function') {
				callbackResult.then(() => {
B
Benjamin Pasero 已提交
126
					if (developerToolsUnbind && options && options.removeDeveloperKeybindingsAfterLoad) {
127 128 129 130 131
						developerToolsUnbind();
					}
				}, error => {
					onUnexpectedError(error, enableDeveloperTools);
				});
132
			}
133 134 135
		} catch (error) {
			onUnexpectedError(error, enableDeveloperTools);
		}
136 137 138
	});
};

139
/**
140 141 142 143 144 145 146 147 148 149 150 151 152 153
 * @returns {{[param: string]: string }}
 */
function parseURLQueryArgs() {
	const search = window.location.search || '';

	return search.split(/[?&]/)
		.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; }, {});
}

/**
 * @returns {() => void}
154
 */
155
function registerDeveloperKeybindings() {
156

157
	// @ts-ignore
158 159 160 161 162 163 164 165 166 167 168 169 170 171
	const ipc = require('electron').ipcRenderer;

	const extractKey = function (e) {
		return [
			e.ctrlKey ? 'ctrl-' : '',
			e.metaKey ? 'meta-' : '',
			e.altKey ? 'alt-' : '',
			e.shiftKey ? 'shift-' : '',
			e.keyCode
		].join('');
	};

	// Devtools & reload support
	const TOGGLE_DEV_TOOLS_KB = (process.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I
B
Benjamin Pasero 已提交
172
	const TOGGLE_DEV_TOOLS_KB_ALT = '123'; // F12
173 174 175 176
	const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R

	let listener = function (e) {
		const key = extractKey(e);
B
Benjamin Pasero 已提交
177
		if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) {
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
			ipc.send('vscode:toggleDevTools');
		} else if (key === RELOAD_KB) {
			ipc.send('vscode:reloadWindow');
		}
	};

	window.addEventListener('keydown', listener);

	return function () {
		if (listener) {
			window.removeEventListener('keydown', listener);
			listener = void 0;
		}
	};
}

function onUnexpectedError(error, enableDeveloperTools) {
195

196
	// @ts-ignore
197 198 199 200 201 202 203 204 205 206 207
	const ipc = require('electron').ipcRenderer;

	if (enableDeveloperTools) {
		ipc.send('vscode:openDevTools');
	}

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

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