diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index b9d66d444a8..9d760ddf101 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -37,6 +37,17 @@ if (process.env['VSCODE_PARENT_PID']) { terminateWhenParentTerminates(); } +// VSCODE_GLOBALS: node_modules +globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { + get(target, mod) { + if (!target[mod] && typeof mod === 'string') { + target[mod] = require(mod); + } + return target[mod]; + } +}); + + // Load AMD entry point require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']); diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 8bdd75c63c0..f8b895c2d77 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -112,6 +112,16 @@ window['MonacoEnvironment'] = {}; + // VSCODE_GLOBALS: node_modules + globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { + get(target, mod) { + if (!target[mod] && typeof mod === 'string') { + target[mod] = (require.__$__nodeRequire ?? require)(mod); + } + return target[mod]; + } + }); + const loaderConfig = { baseUrl: `${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out`, 'vs/nls': nlsConfig, diff --git a/src/main.js b/src/main.js index 63f8c5679f9..4c43e0923b7 100644 --- a/src/main.js +++ b/src/main.js @@ -141,6 +141,16 @@ function startup(codeCachePath, nlsConfig) { process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); process.env['VSCODE_CODE_CACHE_PATH'] = codeCachePath || ''; + // VSCODE_GLOBALS: node_modules + globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { + get(target, mod) { + if (!target[mod] && typeof mod === 'string') { + target[mod] = require(mod); + } + return target[mod]; + } + }); + // Load main in AMD perf.mark('code/willLoadMainBundle'); require('./bootstrap-amd').load('vs/code/electron-main/main', () => { @@ -318,6 +328,7 @@ function getArgvConfigPath() { dataFolderName = `${dataFolderName}-dev`; } + // @ts-ignore return path.join(os.homedir(), dataFolderName, 'argv.json'); } diff --git a/src/typings/vscode-globals.d.ts b/src/typings/vscode-globals.d.ts new file mode 100644 index 00000000000..f8d32c405bf --- /dev/null +++ b/src/typings/vscode-globals.d.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare global { + + /** + * @deprecated node modules that are in used in a context that + * shouldn't have access to node_modules (node-free renderer or + * shared process) + */ + var _VSCODE_NODE_MODULES: { + crypto: typeof import('crypto'); + zlib: typeof import('zlib'); + net: typeof import('net'); + os: typeof import('os'); + module: typeof import('module'); + ['native-watchdog']: typeof import('native-watchdog') + perf_hooks: typeof import('perf_hooks'); + + ['vsda']: any + ['vscode-encrypt']: any + } +} + +// fake export to make global work +export { } diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 15eab308bf2..92e261d898a 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -78,7 +78,7 @@ } else if (typeof process === 'object') { // node.js: use the normal polyfill but add the timeOrigin // from the node perf_hooks API as very first mark - const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin); + const timeOrigin = Math.round((require.__$__nodeRequire || require)('perf_hooks').performance.timeOrigin); return _definePolyfillMarks(timeOrigin); } else { diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index 810ba41d106..455caa3efeb 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -20,10 +20,10 @@ import { ChunkStream, Client, ISocket, Protocol, SocketCloseEvent, SocketCloseEv // TODO@bpasero remove me once electron utility process has landed function getNodeDependencies() { return { - crypto: (require.__$__nodeRequire('crypto') as any) as typeof import('crypto'), - zlib: (require.__$__nodeRequire('zlib') as any) as typeof import('zlib'), - net: (require.__$__nodeRequire('net') as any) as typeof import('net'), - os: (require.__$__nodeRequire('os') as any) as typeof import('os') + crypto: globalThis._VSCODE_NODE_MODULES.crypto, + zlib: globalThis._VSCODE_NODE_MODULES.zlib, + net: globalThis._VSCODE_NODE_MODULES.net, + os: globalThis._VSCODE_NODE_MODULES.os, }; } diff --git a/src/vs/platform/environment/test/node/nativeModules.test.ts b/src/vs/platform/environment/test/node/nativeModules.test.ts index 6b7dfad6741..c538d8c3220 100644 --- a/src/vs/platform/environment/test/node/nativeModules.test.ts +++ b/src/vs/platform/environment/test/node/nativeModules.test.ts @@ -58,7 +58,7 @@ flakySuite('Native Modules (all platforms)', () => { test('vscode-encrypt', async () => { try { - const vscodeEncrypt: Encryption = require.__$__nodeRequire('vscode-encrypt'); + const vscodeEncrypt: Encryption = globalThis._VSCODE_NODE_MODULES['vscode-encrypt']; const encrypted = await vscodeEncrypt.encrypt('salt', 'value'); const decrypted = await vscodeEncrypt.decrypt('salt', encrypted); @@ -73,7 +73,7 @@ flakySuite('Native Modules (all platforms)', () => { test('vsda', async () => { try { - const vsda: any = require.__$__nodeRequire('vsda'); + const vsda: any = globalThis._VSCODE_NODE_MODULES['vsda']; const signer = new vsda.signer(); const signed = await signer.sign('value'); assert.ok(typeof signed === 'string', testErrorMessage('vsda')); diff --git a/src/vs/server/node/remoteExtensionHostAgentServer.ts b/src/vs/server/node/remoteExtensionHostAgentServer.ts index efc591aab18..ce679e09201 100644 --- a/src/vs/server/node/remoteExtensionHostAgentServer.ts +++ b/src/vs/server/node/remoteExtensionHostAgentServer.ts @@ -727,7 +727,7 @@ export async function createServer(address: string | net.AddressInfo | null, arg const hasVSDA = fs.existsSync(join(FileAccess.asFileUri('').fsPath, '../node_modules/vsda')); if (hasVSDA) { try { - return require.__$__nodeRequire('vsda'); + return globalThis._VSCODE_NODE_MODULES['vsda']; } catch (err) { logService.error(err); } diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 32e4f223aad..06f91272771 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -22,7 +22,7 @@ class NodeModuleRequireInterceptor extends RequireInterceptor { protected _installInterceptor(): void { const that = this; - const node_module = require.__$__nodeRequire('module'); + const node_module = globalThis._VSCODE_NODE_MODULES.module; const originalLoad = node_module._load; node_module._load = function load(request: string, parent: { filename: string }, isMain: boolean) { request = applyAlternatives(request); diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts index 5b0030167cd..07289755555 100644 --- a/src/vs/workbench/api/node/extensionHostProcess.ts +++ b/src/vs/workbench/api/node/extensionHostProcess.ts @@ -81,7 +81,7 @@ const args = minimist(process.argv.slice(2), { // happening we essentially blocklist this module from getting loaded in any // extension by patching the node require() function. (function () { - const Module = require.__$__nodeRequire('module') as any; + const Module = globalThis._VSCODE_NODE_MODULES.module as any; const originalLoad = Module._load; Module._load = function (request: string) { @@ -325,7 +325,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise): Promise { return extensionService.getExtensionPathIndex() .then(extensionPaths => { - const node_module = require.__$__nodeRequire('module'); + const node_module = globalThis._VSCODE_NODE_MODULES.module; const original = node_module._load; node_module._load = function load(request: string, parent: { filename: string }, isMain: boolean) { if (request === 'tls') { diff --git a/test/unit/electron/renderer.js b/test/unit/electron/renderer.js index 47f8fb0a53e..3a7cc2fb66e 100644 --- a/test/unit/electron/renderer.js +++ b/test/unit/electron/renderer.js @@ -72,6 +72,16 @@ if (util.inspect && util.inspect['defaultOptions']) { util.inspect['defaultOptions'].customInspect = false; } +// VSCODE_GLOBALS: node_modules +globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { + get(target, mod) { + if (!target[mod] && typeof mod === 'string') { + target[mod] = (require.__$__nodeRequire ?? require)(mod); + } + return target[mod]; + } +}); + const _tests_glob = '**/test/**/*.test.js'; let loader; let _out;