diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index b9d66d444a818..00bf5ed74516d 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -37,10 +37,16 @@ if (process.env['VSCODE_PARENT_PID']) { terminateWhenParentTerminates(); } +// VSCODE_GLOBALS: node_modules +globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { get: (_target, mod) => require(String(mod)) }); + +// VSCODE_GLOBALS: package/product.json +globalThis._VSCODE_PRODUCT_JSON = require('../product.json'); +globalThis._VSCODE_PACKAGE_JSON = require('../package.json'); + // Load AMD entry point require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']); - //#region Helpers function pipeLoggingToParent() { diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 8bdd75c63c088..e4218117b7d06 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -112,6 +112,13 @@ window['MonacoEnvironment'] = {}; + // VSCODE_GLOBALS: node_modules + globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { get: (_target, mod) => (require.__$__nodeRequire ?? require)(String(mod)) }); + + // VSCODE_GLOBALS: package/product.json + globalThis._VSCODE_PRODUCT_JSON = (require.__$__nodeRequire ?? require)(configuration.appRoot + '/product.json'); + globalThis._VSCODE_PACKAGE_JSON = (require.__$__nodeRequire ?? require)(configuration.appRoot + '/package.json'); + 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 63f8c5679f98c..eebc049c6f5bf 100644 --- a/src/main.js +++ b/src/main.js @@ -141,6 +141,13 @@ 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) => require(String(mod)) }); + + // VSCODE_GLOBALS: package/product.json + globalThis._VSCODE_PRODUCT_JSON = require('../product.json'); + globalThis._VSCODE_PACKAGE_JSON = require('../package.json'); + // Load main in AMD perf.mark('code/willLoadMainBundle'); require('./bootstrap-amd').load('vs/code/electron-main/main', () => { @@ -318,6 +325,7 @@ function getArgvConfigPath() { dataFolderName = `${dataFolderName}-dev`; } + // @ts-ignore return path.join(os.homedir(), dataFolderName, 'argv.json'); } diff --git a/src/server-main.js b/src/server-main.js index 27ecbaed0d6af..8eb66e83abf2a 100644 --- a/src/server-main.js +++ b/src/server-main.js @@ -258,6 +258,13 @@ function loadCode() { return new Promise((resolve, reject) => { const path = require('path'); + // VSCODE_GLOBALS: node_modules + globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { get: (_target, mod) => require(String(mod)) }); + + // VSCODE_GLOBALS: package/product.json + globalThis._VSCODE_PRODUCT_JSON = require('../product.json'); + globalThis._VSCODE_PACKAGE_JSON = require('../package.json'); + delete process.env['ELECTRON_RUN_AS_NODE']; // Keep bootstrap-amd.js from redefining 'fs'. // See https://github.com/microsoft/vscode-remote-release/issues/6543 diff --git a/src/tsconfig.monaco.json b/src/tsconfig.monaco.json index 057aa8748ae87..256f406fb6c2a 100644 --- a/src/tsconfig.monaco.json +++ b/src/tsconfig.monaco.json @@ -18,6 +18,7 @@ "include": [ "typings/require.d.ts", "typings/thenable.d.ts", + "typings/vscode-globals-product.d.ts", "vs/loader.d.ts", "vs/monaco.d.ts", "vs/editor/*", diff --git a/src/typings/require.d.ts b/src/typings/require.d.ts index 671692c88daec..3fda6d6981d25 100644 --- a/src/typings/require.d.ts +++ b/src/typings/require.d.ts @@ -45,10 +45,17 @@ interface NodeRequire { * @deprecated use `FileAccess.asFileUri()` for node.js contexts or `FileAccess.asBrowserUri` for browser contexts. */ toUrl(path: string): string; + + /** + * @deprecated MUST not be used anymore + * + * With the move from AMD to ESM we cannot use this anymore. There will be NO MORE node require like this. + */ + __$__nodeRequire(moduleName: string): T; + (dependencies: string[], callback: (...args: any[]) => any, errorback?: (err: any) => void): any; config(data: any): any; onError: Function; - __$__nodeRequire(moduleName: string): T; getStats?(): ReadonlyArray; hasDependencyCycle?(): boolean; define(amdModuleId: string, dependencies: string[], callback: (...args: any[]) => any): any; diff --git a/src/typings/vscode-globals-modules.d.ts b/src/typings/vscode-globals-modules.d.ts new file mode 100644 index 0000000000000..443c2b687db98 --- /dev/null +++ b/src/typings/vscode-globals-modules.d.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AMD2ESM mirgation relevant + +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/typings/vscode-globals-product.d.ts b/src/typings/vscode-globals-product.d.ts new file mode 100644 index 0000000000000..780a6477de86b --- /dev/null +++ b/src/typings/vscode-globals-product.d.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AMD2ESM mirgation relevant + +declare global { + + /** + * @deprecated You MUST use `IProductService` whenever possible. + */ + var _VSCODE_PRODUCT_JSON: Record; + /** + * @deprecated You MUST use `IProductService` whenever possible. + */ + var _VSCODE_PACKAGE_JSON: Record; + +} + +// fake export to make global work +export { } diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 15eab308bf225..92e261d898ab9 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 810ba41d10639..455caa3efeb3c 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 6b7dfad6741d6..c538d8c322084 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/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts index 3f50bef5ca23c..ef798fa469904 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -3,11 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { FileAccess } from 'vs/base/common/network'; import { globals } from 'vs/base/common/platform'; import { env } from 'vs/base/common/process'; import { IProductConfiguration } from 'vs/base/common/product'; -import { dirname, joinPath } from 'vs/base/common/resources'; import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes'; /** @@ -24,14 +22,10 @@ if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.context !== ' throw new Error('Sandbox: unable to resolve product configuration from preload script.'); } } - -// Native node.js environment -else if (typeof require?.__$__nodeRequire === 'function') { - - // Obtain values from product.json and package.json - const rootPath = dirname(FileAccess.asFileUri('')); - - product = require.__$__nodeRequire(joinPath(rootPath, 'product.json').fsPath); +// _VSCODE environment +else if (globalThis._VSCODE_PRODUCT_JSON && globalThis._VSCODE_PACKAGE_JSON) { + // Obtain values from product.json and package.json-data + product = globalThis._VSCODE_PRODUCT_JSON as IProductConfiguration; // Running out of sources if (env['VSCODE_DEV']) { @@ -47,7 +41,7 @@ else if (typeof require?.__$__nodeRequire === 'function') { // want to have it running out of sources so we // read it from package.json only when we need it. if (!product.version) { - const pkg = require.__$__nodeRequire(joinPath(rootPath, 'package.json').fsPath) as { version: string }; + const pkg = globalThis._VSCODE_PACKAGE_JSON as { version: string }; Object.assign(product, { version: pkg.version diff --git a/src/vs/server/node/remoteExtensionHostAgentServer.ts b/src/vs/server/node/remoteExtensionHostAgentServer.ts index efc591aab1847..ce679e092012f 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 32e4f223aadef..06f91272771e8 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 5b0030167cd9e..072897555558e 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 47f8fb0a53ee0..a91725887a52a 100644 --- a/test/unit/electron/renderer.js +++ b/test/unit/electron/renderer.js @@ -72,6 +72,13 @@ 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) => (require.__$__nodeRequire ?? require)(String(mod)) }); + +// VSCODE_GLOBALS: package/product.json +globalThis._VSCODE_PRODUCT_JSON = (require.__$__nodeRequire ?? require)('../../../product.json'); +globalThis._VSCODE_PACKAGE_JSON = (require.__$__nodeRequire ?? require)('../../../package.json'); + const _tests_glob = '**/test/**/*.test.js'; let loader; let _out; diff --git a/test/unit/node/index.js b/test/unit/node/index.js index 1fb4fd570202d..c6474162dfc62 100644 --- a/test/unit/node/index.js +++ b/test/unit/node/index.js @@ -56,6 +56,15 @@ if (majorRequiredNodeVersion !== currentMajorNodeVersion) { } function main() { + + // VSCODE_GLOBALS: node_modules + globalThis._VSCODE_NODE_MODULES = new Proxy(Object.create(null), { get: (_target, mod) => require(String(mod)) }); + + // VSCODE_GLOBALS: package/product.json + globalThis._VSCODE_PRODUCT_JSON = require(`${REPO_ROOT}/product.json`); + globalThis._VSCODE_PACKAGE_JSON = require(`${REPO_ROOT}/package.json`); + + process.on('uncaughtException', function (e) { console.error(e.stack || e); });