bootstrap-window.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. /// <reference path="typings/require.d.ts" />
  6. //@ts-check
  7. 'use strict';
  8. /* eslint-disable no-restricted-globals */
  9. // Simple module style to support node.js and browser environments
  10. (function (globalThis, factory) {
  11. // Node.js
  12. if (typeof exports === 'object') {
  13. module.exports = factory();
  14. }
  15. // Browser
  16. else {
  17. // @ts-ignore
  18. globalThis.MonacoBootstrapWindow = factory();
  19. }
  20. }(this, function () {
  21. const bootstrapLib = bootstrap();
  22. const preloadGlobals = sandboxGlobals();
  23. const safeProcess = preloadGlobals.process;
  24. /**
  25. * @typedef {import('./vs/base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
  26. *
  27. * @param {string[]} modulePaths
  28. * @param {(result: unknown, configuration: ISandboxConfiguration) => Promise<unknown> | undefined} resultCallback
  29. * @param {{
  30. * configureDeveloperSettings?: (config: ISandboxConfiguration) => {
  31. * forceDisableShowDevtoolsOnError?: boolean,
  32. * forceEnableDeveloperKeybindings?: boolean,
  33. * disallowReloadKeybinding?: boolean,
  34. * removeDeveloperKeybindingsAfterLoad?: boolean
  35. * },
  36. * canModifyDOM?: (config: ISandboxConfiguration) => void,
  37. * beforeLoaderConfig?: (loaderConfig: object) => void,
  38. * beforeRequire?: (config: ISandboxConfiguration) => void
  39. * }} [options]
  40. */
  41. async function load(modulePaths, resultCallback, options) {
  42. // Await window configuration from preload
  43. const timeout = setTimeout(() => { console.error(`[resolve window config] Could not resolve window configuration within 10 seconds, but will continue to wait...`); }, 10000);
  44. performance.mark('code/willWaitForWindowConfig');
  45. /** @type {ISandboxConfiguration} */
  46. const configuration = await preloadGlobals.context.resolveConfiguration();
  47. performance.mark('code/didWaitForWindowConfig');
  48. clearTimeout(timeout);
  49. // Signal DOM modifications are now OK
  50. if (typeof options?.canModifyDOM === 'function') {
  51. options.canModifyDOM(configuration);
  52. }
  53. // Developer settings
  54. const {
  55. forceEnableDeveloperKeybindings,
  56. disallowReloadKeybinding,
  57. removeDeveloperKeybindingsAfterLoad
  58. } = typeof options?.configureDeveloperSettings === 'function' ? options.configureDeveloperSettings(configuration) : {
  59. forceEnableDeveloperKeybindings: false,
  60. disallowReloadKeybinding: false,
  61. removeDeveloperKeybindingsAfterLoad: false
  62. };
  63. const isDev = !!safeProcess.env['VSCODE_DEV'];
  64. const enableDeveloperKeybindings = isDev || forceEnableDeveloperKeybindings;
  65. /**
  66. * @type {() => void | undefined}
  67. */
  68. let developerDeveloperKeybindingsDisposable;
  69. if (enableDeveloperKeybindings) {
  70. developerDeveloperKeybindingsDisposable = registerDeveloperKeybindings(disallowReloadKeybinding);
  71. }
  72. // Get the nls configuration into the process.env as early as possible
  73. // @ts-ignore
  74. const nlsConfig = globalThis.MonacoBootstrap.setupNLS();
  75. let locale = nlsConfig.availableLanguages['*'] || 'en';
  76. if (locale === 'zh-tw') {
  77. locale = 'zh-Hant';
  78. } else if (locale === 'zh-cn') {
  79. locale = 'zh-Hans';
  80. }
  81. window.document.documentElement.setAttribute('lang', locale);
  82. window['MonacoEnvironment'] = {};
  83. /**
  84. * @typedef {any} LoaderConfig
  85. */
  86. /** @type {LoaderConfig} */
  87. const loaderConfig = {
  88. baseUrl: `${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out`,
  89. 'vs/nls': nlsConfig,
  90. preferScriptTags: true
  91. };
  92. // use a trusted types policy when loading via script tags
  93. loaderConfig.trustedTypesPolicy = window.trustedTypes?.createPolicy('amdLoader', {
  94. createScriptURL(value) {
  95. if (value.startsWith(window.location.origin)) {
  96. return value;
  97. }
  98. throw new Error(`Invalid script url: ${value}`);
  99. }
  100. });
  101. // Teach the loader the location of the node modules we use in renderers
  102. // This will enable to load these modules via <script> tags instead of
  103. // using a fallback such as node.js require which does not exist in sandbox
  104. const baseNodeModulesPath = isDev ? '../node_modules' : '../node_modules.asar';
  105. loaderConfig.paths = {
  106. 'vscode-textmate': `${baseNodeModulesPath}/vscode-textmate/release/main.js`,
  107. 'vscode-oniguruma': `${baseNodeModulesPath}/vscode-oniguruma/release/main.js`,
  108. 'vsda': `${baseNodeModulesPath}/vsda/index.js`,
  109. '@xterm/xterm': `${baseNodeModulesPath}/@xterm/xterm/lib/xterm.js`,
  110. '@xterm/addon-image': `${baseNodeModulesPath}/@xterm/addon-image/lib/addon-image.js`,
  111. '@xterm/addon-search': `${baseNodeModulesPath}/@xterm/addon-search/lib/addon-search.js`,
  112. '@xterm/addon-serialize': `${baseNodeModulesPath}/@xterm/addon-serialize/lib/addon-serialize.js`,
  113. '@xterm/addon-unicode11': `${baseNodeModulesPath}/@xterm/addon-unicode11/lib/addon-unicode11.js`,
  114. '@xterm/addon-webgl': `${baseNodeModulesPath}/@xterm/addon-webgl/lib/addon-webgl.js`,
  115. '@vscode/iconv-lite-umd': `${baseNodeModulesPath}/@vscode/iconv-lite-umd/lib/iconv-lite-umd.js`,
  116. 'jschardet': `${baseNodeModulesPath}/jschardet/dist/jschardet.min.js`,
  117. '@vscode/vscode-languagedetection': `${baseNodeModulesPath}/@vscode/vscode-languagedetection/dist/lib/index.js`,
  118. 'vscode-regexp-languagedetection': `${baseNodeModulesPath}/vscode-regexp-languagedetection/dist/index.js`,
  119. 'tas-client-umd': `${baseNodeModulesPath}/tas-client-umd/lib/tas-client-umd.js`
  120. };
  121. // Signal before require.config()
  122. if (typeof options?.beforeLoaderConfig === 'function') {
  123. options.beforeLoaderConfig(loaderConfig);
  124. }
  125. // Configure loader
  126. require.config(loaderConfig);
  127. // Handle pseudo NLS
  128. if (nlsConfig.pseudo) {
  129. require(['vs/nls'], function (nlsPlugin) {
  130. nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
  131. });
  132. }
  133. // Signal before require()
  134. if (typeof options?.beforeRequire === 'function') {
  135. options.beforeRequire(configuration);
  136. }
  137. // Actually require the main module as specified
  138. require(modulePaths, async firstModule => {
  139. try {
  140. // Callback only after process environment is resolved
  141. const callbackResult = resultCallback(firstModule, configuration);
  142. if (callbackResult instanceof Promise) {
  143. await callbackResult;
  144. if (developerDeveloperKeybindingsDisposable && removeDeveloperKeybindingsAfterLoad) {
  145. developerDeveloperKeybindingsDisposable();
  146. }
  147. }
  148. } catch (error) {
  149. onUnexpectedError(error, enableDeveloperKeybindings);
  150. }
  151. }, onUnexpectedError);
  152. }
  153. /**
  154. * @param {boolean | undefined} disallowReloadKeybinding
  155. * @returns {() => void}
  156. */
  157. function registerDeveloperKeybindings(disallowReloadKeybinding) {
  158. const ipcRenderer = preloadGlobals.ipcRenderer;
  159. const extractKey =
  160. /**
  161. * @param {KeyboardEvent} e
  162. */
  163. function (e) {
  164. return [
  165. e.ctrlKey ? 'ctrl-' : '',
  166. e.metaKey ? 'meta-' : '',
  167. e.altKey ? 'alt-' : '',
  168. e.shiftKey ? 'shift-' : '',
  169. e.keyCode
  170. ].join('');
  171. };
  172. // Devtools & reload support
  173. const TOGGLE_DEV_TOOLS_KB = (safeProcess.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I
  174. const TOGGLE_DEV_TOOLS_KB_ALT = '123'; // F12
  175. const RELOAD_KB = (safeProcess.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R
  176. /** @type {((e: KeyboardEvent) => void) | undefined} */
  177. let listener = function (e) {
  178. const key = extractKey(e);
  179. if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) {
  180. ipcRenderer.send('vscode:toggleDevTools');
  181. } else if (key === RELOAD_KB && !disallowReloadKeybinding) {
  182. ipcRenderer.send('vscode:reloadWindow');
  183. }
  184. };
  185. window.addEventListener('keydown', listener);
  186. return function () {
  187. if (listener) {
  188. window.removeEventListener('keydown', listener);
  189. listener = undefined;
  190. }
  191. };
  192. }
  193. /**
  194. * @param {string | Error} error
  195. * @param {boolean} [showDevtoolsOnError]
  196. */
  197. function onUnexpectedError(error, showDevtoolsOnError) {
  198. if (showDevtoolsOnError) {
  199. const ipcRenderer = preloadGlobals.ipcRenderer;
  200. ipcRenderer.send('vscode:openDevTools');
  201. }
  202. console.error(`[uncaught exception]: ${error}`);
  203. if (error && typeof error !== 'string' && error.stack) {
  204. console.error(error.stack);
  205. }
  206. }
  207. /**
  208. * @return {{ fileUriFromPath: (path: string, config: { isWindows?: boolean, scheme?: string, fallbackAuthority?: string }) => string; }}
  209. */
  210. function bootstrap() {
  211. // @ts-ignore (defined in bootstrap.js)
  212. return window.MonacoBootstrap;
  213. }
  214. /**
  215. * @return {typeof import('./vs/base/parts/sandbox/electron-sandbox/globals')}
  216. */
  217. function sandboxGlobals() {
  218. // @ts-ignore (defined in globals.js)
  219. return window.vscode;
  220. }
  221. return {
  222. load
  223. };
  224. }));