mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
361
src/main.js
361
src/main.js
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user