Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)

* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998

* fix pipelines

* fix strict-null-checks

* add missing files
This commit is contained in:
Anthony Dresser
2019-10-21 22:12:22 -07:00
committed by GitHub
parent 7c9be74970
commit 1e22f47304
913 changed files with 18898 additions and 16536 deletions

View File

@@ -12,12 +12,14 @@ const lp = require('./vs/base/node/languagePacks');
perf.mark('main:started');
const path = require('path');
const fs = require('fs');
const os = require('os');
const bootstrap = require('./bootstrap');
const paths = require('./paths');
// @ts-ignore
const product = require('../product.json');
// @ts-ignore
const app = require('electron').app;
const { app, protocol } = require('electron');
// Enable portable support
const portable = bootstrap.configurePortable();
@@ -25,7 +27,7 @@ const portable = bootstrap.configurePortable();
// Enable ASAR support
bootstrap.enableASARSupport();
// Set userData path before app 'ready' event and call to process.chdir
// Set userData path before app 'ready' event
const args = parseCLIArgs();
if (args['nogpu']) { // {{SQL CARBON EDIT}}
@@ -37,32 +39,44 @@ if (args['nogpu']) { // {{SQL CARBON EDIT}}
const userDataPath = getUserDataPath(args);
app.setPath('userData', userDataPath);
// Set logs path before app 'ready' event if running portable
// to ensure that no 'logs' folder is created on disk at a
// location outside of the portable directory
// (https://github.com/microsoft/vscode/issues/56651)
if (portable.isPortable) {
app.setAppLogsPath(path.join(userDataPath, 'logs'));
}
// Update cwd based on environment and platform
setCurrentWorkingDirectory();
// Register custom schemes with privileges
protocol.registerSchemesAsPrivileged([
{ scheme: 'vscode-resource', privileges: { secure: true, supportFetchAPI: true, corsEnabled: true } }
]);
// Global app listeners
registerListeners();
/**
* Support user defined locale
*
* @type {Promise}
*/
let nlsConfiguration = undefined;
const userDefinedLocale = getUserDefinedLocale();
const metaDataFile = path.join(__dirname, 'nls.metadata.json');
userDefinedLocale.then(locale => {
if (locale && !nlsConfiguration) {
nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
}
});
// Cached data
const nodeCachedDataDir = getNodeCachedDir();
// Configure command line switches
configureCommandlineSwitches(args);
// Configure static command line arguments
const argvConfig = configureCommandlineSwitchesSync(args);
/**
* Support user defined locale: load it early before app('ready')
* to have more things running in parallel.
*
* @type {Promise<import('./vs/base/node/languagePacks').NLSConfiguration>} nlsConfig | undefined
*/
let nlsConfigurationPromise = undefined;
const metaDataFile = path.join(__dirname, 'nls.metadata.json');
const locale = getUserDefinedLocale(argvConfig);
if (locale) {
nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
}
// Load our code once ready
app.once('ready', function () {
@@ -81,62 +95,35 @@ app.once('ready', function () {
}
});
function onReady() {
/**
* Main startup routine
*
* @param {string | undefined} cachedDataDir
* @param {import('./vs/base/node/languagePacks').NLSConfiguration} nlsConfig
*/
function startup(cachedDataDir, nlsConfig) {
nlsConfig._languagePackSupport = true;
process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || '';
// Load main in AMD
perf.mark('willLoadMainBundle');
require('./bootstrap-amd').load('vs/code/electron-main/main', () => {
perf.mark('didLoadMainBundle');
});
}
async function onReady() {
perf.mark('main:appReady');
Promise.all([nodeCachedDataDir.ensureExists(), userDefinedLocale]).then(([cachedDataDir, locale]) => {
if (locale && !nlsConfiguration) {
nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
}
try {
const [cachedDataDir, nlsConfig] = await Promise.all([nodeCachedDataDir.ensureExists(), resolveNlsConfiguration()]);
if (!nlsConfiguration) {
nlsConfiguration = Promise.resolve(undefined);
}
// First, we need to test a user defined locale. If it fails we try the app locale.
// If that fails we fall back to English.
nlsConfiguration.then(nlsConfig => {
const startup = nlsConfig => {
nlsConfig._languagePackSupport = true;
process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || '';
// Load main in AMD
perf.mark('willLoadMainBundle');
require('./bootstrap-amd').load('vs/code/electron-main/main', () => {
perf.mark('didLoadMainBundle');
});
};
// We received a valid nlsConfig from a user defined locale
if (nlsConfig) {
startup(nlsConfig);
}
// Try to use the app locale. Please note that the app locale is only
// valid after we have received the app ready event. This is why the
// code is here.
else {
let appLocale = app.getLocale();
if (!appLocale) {
startup({ locale: 'en', availableLanguages: {} });
} else {
// See above the comment about the loader and case sensitiviness
appLocale = appLocale.toLowerCase();
lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale).then(nlsConfig => {
if (!nlsConfig) {
nlsConfig = { locale: appLocale, availableLanguages: {} };
}
startup(nlsConfig);
});
}
}
});
}, console.error);
startup(cachedDataDir, nlsConfig);
} catch (error) {
console.error(error);
}
}
/**
@@ -144,16 +131,147 @@ function onReady() {
*
* @param {ParsedArgs} cliArgs
*/
function configureCommandlineSwitches(cliArgs) {
function configureCommandlineSwitchesSync(cliArgs) {
const SUPPORTED_ELECTRON_SWITCHES = [
// Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791)
app.commandLine.appendSwitch('disable-color-correct-rendering');
// alias from us for --disable-gpu
'disable-hardware-acceleration',
// provided by Electron
'disable-color-correct-rendering'
];
// Read argv config
const argvConfig = readArgvConfigSync();
// Append each flag to Electron
Object.keys(argvConfig).forEach(argvKey => {
if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) === -1) {
return; // unsupported argv key
}
const argvValue = argvConfig[argvKey];
if (argvValue === true || argvValue === 'true') {
if (argvKey === 'disable-hardware-acceleration') {
app.disableHardwareAcceleration(); // needs to be called explicitly
} else {
app.commandLine.appendArgument(argvKey);
}
} else {
app.commandLine.appendSwitch(argvKey, argvValue);
}
});
// Support JS Flags
const jsFlags = getJSFlags(cliArgs);
if (jsFlags) {
app.commandLine.appendSwitch('--js-flags', jsFlags);
app.commandLine.appendSwitch('js-flags', jsFlags);
}
return argvConfig;
}
function readArgvConfigSync() {
// Read or create the argv.json config file sync before app('ready')
const argvConfigPath = getArgvConfigPath();
let argvConfig;
try {
argvConfig = JSON.parse(stripComments(fs.readFileSync(argvConfigPath).toString()));
} catch (error) {
if (error && error.code === 'ENOENT') {
createDefaultArgvConfigSync(argvConfigPath);
} else {
console.warn(`Unable to read argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
}
}
// Fallback to default
if (!argvConfig) {
argvConfig = {
'disable-color-correct-rendering': true // Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791)
};
}
return argvConfig;
}
/**
* @param {string} argvConfigPath
*/
function createDefaultArgvConfigSync(argvConfigPath) {
try {
// Ensure argv config parent exists
const argvConfigPathDirname = path.dirname(argvConfigPath);
if (!fs.existsSync(argvConfigPathDirname)) {
fs.mkdirSync(argvConfigPathDirname);
}
// Migrate over legacy locale
const localeConfigPath = path.join(userDataPath, 'User', 'locale.json');
const legacyLocale = getLegacyUserDefinedLocaleSync(localeConfigPath);
if (legacyLocale) {
try {
fs.unlinkSync(localeConfigPath);
} catch (error) {
//ignore
}
}
// Default argv content
const defaultArgvConfigContent = [
'// This configuration file allows to pass permanent command line arguments to VSCode.',
'// Only a subset of arguments is currently supported to reduce the likelyhood of breaking',
'// the installation.',
'//',
'// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT',
'//',
'// If the command line argument does not have any values, simply assign',
'// it in the JSON below with a value of \'true\'. Otherwise, put the value',
'// directly.',
'//',
'// If you see rendering issues in VSCode and have a better experience',
'// with software rendering, you can configure this by adding:',
'//',
'// \'disable-hardware-acceleration\': true',
'//',
'// NOTE: Changing this file requires a restart of VSCode.',
'{',
' // Enabled by default by VSCode to resolve color issues in the renderer',
' // See https://github.com/Microsoft/vscode/issues/51791 for details',
' "disable-color-correct-rendering": true'
];
if (legacyLocale) {
defaultArgvConfigContent[defaultArgvConfigContent.length - 1] = `${defaultArgvConfigContent[defaultArgvConfigContent.length - 1]},`; // append trailing ","
defaultArgvConfigContent.push('');
defaultArgvConfigContent.push(' // Display language of VSCode');
defaultArgvConfigContent.push(` "locale": "${legacyLocale}"`);
}
defaultArgvConfigContent.push('}');
// Create initial argv.json with default content
fs.writeFileSync(argvConfigPath, defaultArgvConfigContent.join('\n'));
} catch (error) {
console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
}
}
function getArgvConfigPath() {
const vscodePortable = process.env['VSCODE_PORTABLE'];
if (vscodePortable) {
return path.join(vscodePortable, 'argv.json');
}
let dataFolderName = product.dataFolderName;
if (process.env['VSCODE_DEV']) {
dataFolderName = `${dataFolderName}-dev`;
}
return path.join(os.homedir(), dataFolderName, 'argv.json');
}
/**
@@ -256,7 +374,7 @@ function registerListeners() {
}
/**
* @returns {{ ensureExists: () => Promise<string | void> }}
* @returns {{ ensureExists: () => Promise<string | undefined> }}
*/
function getNodeCachedDir() {
return new class {
@@ -265,8 +383,14 @@ function getNodeCachedDir() {
this.value = this._compute();
}
ensureExists() {
return bootstrap.mkdirp(this.value).then(() => this.value, () => { /*ignore*/ });
async ensureExists() {
try {
await bootstrap.mkdirp(this.value);
return this.value;
} catch (error) {
// ignore
}
}
_compute() {
@@ -291,6 +415,41 @@ function getNodeCachedDir() {
}
//#region NLS Support
/**
* Resolve the NLS configuration
*
* @return {Promise<import('./vs/base/node/languagePacks').NLSConfiguration>}
*/
async function resolveNlsConfiguration() {
// First, we need to test a user defined locale. If it fails we try the app locale.
// If that fails we fall back to English.
let nlsConfiguration = nlsConfigurationPromise ? await nlsConfigurationPromise : undefined;
if (!nlsConfiguration) {
// Try to use the app locale. Please note that the app locale is only
// valid after we have received the app ready event. This is why the
// code is here.
let appLocale = app.getLocale();
if (!appLocale) {
nlsConfiguration = { locale: 'en', availableLanguages: {} };
} else {
// See above the comment about the loader and case sensitiviness
appLocale = appLocale.toLowerCase();
nlsConfiguration = await lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
if (!nlsConfiguration) {
nlsConfiguration = { locale: appLocale, availableLanguages: {} };
}
}
} else {
// We received a valid nlsConfig from a user defined locale
}
return nlsConfiguration;
}
/**
* @param {string} content
* @returns {string}
@@ -319,30 +478,36 @@ function stripComments(content) {
});
}
// Language tags are case insensitive however an amd loader is case sensitive
// To make this work on case preserving & insensitive FS we do the following:
// the language bundles have lower case language tags and we always lower case
// the locale we receive from the user or OS.
/**
* @returns {Promise<string>}
* Language tags are case insensitive however an amd loader is case sensitive
* To make this work on case preserving & insensitive FS we do the following:
* the language bundles have lower case language tags and we always lower case
* the locale we receive from the user or OS.
*
* @param {{ locale: string | undefined; }} argvConfig
* @returns {string | undefined}
*/
function getUserDefinedLocale() {
function getUserDefinedLocale(argvConfig) {
const locale = args['locale'];
if (locale) {
return Promise.resolve(locale.toLowerCase());
return locale.toLowerCase(); // a directly provided --locale always wins
}
const localeConfig = path.join(userDataPath, 'User', 'locale.json');
return bootstrap.readFile(localeConfig).then(content => {
content = stripComments(content);
try {
const value = JSON.parse(content).locale;
return value && typeof value === 'string' ? value.toLowerCase() : undefined;
} catch (e) {
return undefined;
}
}, () => {
return undefined;
});
return argvConfig.locale && typeof argvConfig.locale === 'string' ? argvConfig.locale.toLowerCase() : undefined;
}
/**
* @param {string} localeConfigPath
* @returns {string | undefined}
*/
function getLegacyUserDefinedLocaleSync(localeConfigPath) {
try {
const content = stripComments(fs.readFileSync(localeConfigPath).toString());
const value = JSON.parse(content).locale;
return value && typeof value === 'string' ? value.toLowerCase() : undefined;
} catch (error) {
// ignore
}
}
//#endregion