diff --git a/src/extension/debugger/attachQuickPick/provider.ts b/src/extension/debugger/attachQuickPick/provider.ts index b7cee524..29ab46a7 100644 --- a/src/extension/debugger/attachQuickPick/provider.ts +++ b/src/extension/debugger/attachQuickPick/provider.ts @@ -3,7 +3,8 @@ 'use strict'; -import { l10n } from 'vscode'; +import * as path from 'path'; +import { env, l10n } from 'vscode'; import type { IProcessInfo } from '@vscode/windows-process-tree'; import { getOSType, OSType } from '../../common/platform'; import { PsProcessParser } from './psProcessParser'; @@ -16,6 +17,14 @@ import { logProcess } from '../../common/process/logger'; export class AttachProcessProvider implements IAttachProcessProvider { constructor() {} + public _loadWindowsProcessTree(): typeof import('@vscode/windows-process-tree') { + const wpcPath = path.join(env.appRoot, 'node_modules', '@vscode', 'windows-process-tree'); + // Use eval to bypass webpack's require interception for loading native addon at runtime + // eslint-disable-next-line no-eval + const nodeRequire = eval('require') as NodeJS.Require; + return nodeRequire(wpcPath); + } + public getAttachItems(): Promise { return this._getInternalProcessEntries().then((processEntries) => { processEntries.sort( @@ -63,7 +72,7 @@ export class AttachProcessProvider implements IAttachProcessProvider { if (osType === OSType.Windows) { try { - const wpc = require('@vscode/windows-process-tree'); + const wpc = this._loadWindowsProcessTree(); const processList = await new Promise((resolve) => { wpc.getAllProcesses( (processes: IProcessInfo[]) => resolve(processes), diff --git a/src/test/unittest/attachQuickPick/provider.unit.test.ts b/src/test/unittest/attachQuickPick/provider.unit.test.ts index 90b5dbec..1e32d691 100644 --- a/src/test/unittest/attachQuickPick/provider.unit.test.ts +++ b/src/test/unittest/attachQuickPick/provider.unit.test.ts @@ -13,7 +13,6 @@ import { IAttachItem } from '../../../extension/debugger/attachQuickPick/types'; import { WmicProcessParser } from '../../../extension/debugger/attachQuickPick/wmicProcessParser'; import * as platform from '../../../extension/common/platform'; import * as rawProcessApis from '../../../extension/common/process/rawProcessApis'; -import * as wpc from '@vscode/windows-process-tree'; use(chaiAsPromised); @@ -27,7 +26,12 @@ suite('Attach to process - process provider', () => { provider = new AttachProcessProvider(); getOSTypeStub = sinon.stub(platform, 'getOSType'); plainExecStub = sinon.stub(rawProcessApis, 'plainExec'); - getAllProcessesStub = sinon.stub(wpc, 'getAllProcesses'); + getAllProcessesStub = sinon.stub(); + sinon.stub(provider, '_loadWindowsProcessTree').returns({ + getAllProcesses: getAllProcessesStub, + // eslint-disable-next-line @typescript-eslint/naming-convention + ProcessDataFlag: { None: 0, Memory: 1, CommandLine: 2 }, + } as any); }); teardown(() => { diff --git a/webpack.config.js b/webpack.config.js index 8cca6f28..5314c123 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -38,7 +38,7 @@ const extensionConfig = { '@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', // ignored because we don't ship instrumentation '@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', // ignored because we don't ship instrumentation '@azure/functions-core': '@azure/functions-core', // ignored because we don't ship instrumentation - '@vscode/windows-process-tree': 'commonjs @vscode/windows-process-tree', // native addon (.node binary); webpack cannot bundle it, resolved at runtime via VS Code's built-in copy + '@vscode/windows-process-tree': 'commonjs @vscode/windows-process-tree', // native addon (.node binary); webpack cannot bundle it. Loaded at runtime via vscode.env.appRoot absolute path using eval('require') to bypass webpack's require interception }, resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader