bootstrap-window.js 5.7 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 11 12 13 14 15 16 17 18 19 20
const bootstrap = require('./bootstrap');

exports.parseURLQueryArgs = function () {
	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; }, {});
};

21 22 23 24 25 26
/**
 * @param {object} destination
 * @param {object} source
 * @returns {object}
 */
exports.assign = function assign(destination, source) {
27 28 29
	return Object.keys(source).reduce(function (r, key) { r[key] = source[key]; return r; }, destination);
};

30 31 32 33
/**
 *
 * @param {string[]} modulePaths
 * @param {(result, configuration) => any} resultCallback
B
Benjamin Pasero 已提交
34
 * @param {{ forceEnableDeveloperKeybindings?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config) => void, beforeLoaderConfig?: (config, loaderConfig) => void, beforeRequire?: () => void }=} options
35
 */
36
exports.load = function (modulePaths, resultCallback, options) {
37
	// @ts-ignore
38 39 40 41 42 43
	const webFrame = require('electron').webFrame;

	const args = exports.parseURLQueryArgs();
	const configuration = JSON.parse(args['config'] || '{}') || {};

	// Error handler
44
	// @ts-ignore
45 46 47 48 49
	process.on('uncaughtException', function (error) { onUnexpectedError(error, enableDeveloperTools); });

	// Developer tools
	const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath;
	let developerToolsUnbind;
B
Benjamin Pasero 已提交
50
	if (enableDeveloperTools || (options && options.forceEnableDeveloperKeybindings)) {
51 52 53 54 55 56 57
		developerToolsUnbind = registerDeveloperKeybindings();
	}

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

	// Enable ASAR support
B
Benjamin Pasero 已提交
58
	bootstrap.enableASARSupport();
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

	// 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
84 85 86 87
	const amdLoader = require(configuration.appRoot + '/out/vs/loader.js');
	const amdRequire = amdLoader.require;
	const amdDefine = amdLoader.require.define;
	const nodeRequire = amdLoader.require.nodeRequire;
88

89 90
	window['nodeRequire'] = nodeRequire;
	window['require'] = amdRequire;
91

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

95
	window['MonacoEnvironment'] = {};
96

97 98 99 100 101 102
	const loaderConfig = {
		baseUrl: bootstrap.uriFromPath(configuration.appRoot) + '/out',
		'vs/nls': nlsConfig,
		nodeCachedDataDir: configuration.nodeCachedDataDir,
		nodeModules: [/*BUILD->INSERT_NODE_MODULES*/]
	};
103

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

108
	amdRequire.config(loaderConfig);
109

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

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

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

138 139 140
/**
 * @returns () => void
 */
141
function registerDeveloperKeybindings() {
142
	// @ts-ignore
143 144 145 146 147 148 149 150 151 152 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
	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
	const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R

	let listener = function (e) {
		const key = extractKey(e);
		if (key === TOGGLE_DEV_TOOLS_KB) {
			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) {
179
	// @ts-ignore
180 181 182 183 184 185 186 187 188 189 190 191
	const ipc = require('electron').ipcRenderer;

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

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

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