Skip to content

Migrate extension and tooling to native ESM - #9640

Open
dibarbet wants to merge 2 commits into
dev/dibarbet/explicit-ts-importsfrom
dibarbet-dev-dibarbet-esm-migration-stack
Open

Migrate extension and tooling to native ESM#9640
dibarbet wants to merge 2 commits into
dev/dibarbet/explicit-ts-importsfrom
dibarbet-dev-dibarbet-esm-migration-stack

Conversation

@dibarbet

@dibarbet dibarbet commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

This is the top layer stacked on #9637 (dev/dibarbet/explicit-ts-imports). It contains the remaining changes from #9635 after the explicit .ts imports and preparatory tooling changes owned by the bottom layer.

The committed final tree is byte-for-byte identical to #9635 at ede27cfb7824ecb862f69991ff872ebeea0a968f.

  • adopt package-native ESM and TypeScript NodeNext
  • switch extension, esbuild, Jest, and build/test entry points to .mjs
  • add the createRequire(import.meta.url) bridge for bundled CommonJS dependencies
  • add development/production bundle audits and artifact coverage for the native ESM extension entry

Validation

  • npm run compileDev
  • npm run test:unit
  • npm run omnisharptest:unit
  • npm run package
  • node --check dist/extension.mjs
  • node esbuild.mjs
  • node esbuild.mjs --production
  • npm run vsix:release:package
  • npm run test:artifacts
  • git diff --check

#9635 will be superseded after this two-PR chain is registered as a native GitHub stack. Stack metadata registration and closure of #9635 are intentionally deferred to the coordinator.

Adopt package-native ESM, NodeNext compilation, .mjs build and Jest entry points, the createRequire compatibility bridge, and bundle audits.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 46c7e712-4c83-454d-ace4-38b72163a59b
Define __filename and __dirname from import.meta.url so bundled CommonJS dependencies such as the Razor component can activate under native ESM.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 518234fc-e4aa-431d-bf7d-36223e1440b1
Copilot AI review requested due to automatic review settings August 5, 2026 18:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request completes the repo-wide migration of the VS Code C# extension and its build/test tooling from CommonJS to native ESM, switching TypeScript to NodeNext and updating packaging, Jest configuration, and runtime bridges needed for CommonJS dependencies.

Changes:

  • Adopt package-native ESM ("type": "module") and emit/ship dist/extension.mjs with updated esbuild and signing support.
  • Convert Jest + test entry points/configuration to .mjs, introduce centralized jestProjectNames, and update mocks to work under ESM.
  • Add bundle auditing (dev/prod) to enforce a stable createRequire(import.meta.url) bridge boundary and verify extension entry + VSIX content.
Show a summary per file
File Description
wallaby.js Convert Wallaby config to ESM export style.
tsconfig.json Switch TS compilation to NodeNext/ESM-oriented settings and narrower include globs.
tsconfig.jest.json Add Jest-specific TS config override for CommonJS projects.
test/vsCodeUnitFramework.ts Add unit-test setup for virtual vscode mocking under ESM Jest.
test/vsCodeFramework.ts Extend existing VS Code test setup to include ESM mocking path.
test/vsCodeEnvironment.ts Convert custom Jest environment export to ESM-compatible default export.
test/untrustedWorkspace/integrationTests/jest.config.mjs Migrate untrusted integration Jest config to .mjs and shared project naming.
test/untrustedWorkspace/integrationTests/index.ts Use shared Jest project names for untrusted integration runner.
test/tasks/jest.config.mjs Migrate tasks unit Jest config to .mjs and shared project naming.
test/tasks/bundleAudit.test.js Add unit test coverage for bundle audit rejecting first-party runtime requires.
test/runIntegrationTests.ts Update integration test runner to use ESM jest import and .mjs root config.
test/razor/razorTests/Microsoft.AspNetCore.Razor.VSCode.Grammar.Test/tests/infrastructure/tokenizedContentProvider.ts Adjust Razor grammar test infra for ESM (import.meta.url) and default imports for CJS deps.
test/razor/razorTests/jest.config.mjs Migrate Razor unit Jest config to .mjs and shared project naming.
test/razor/razorIntegrationTests/jest.config.mjs Migrate Razor integration Jest config to .mjs and shared project naming.
test/razor/razorIntegrationTests/index.ts Use shared Jest project names for Razor integration runner.
test/omnisharp/runFeatureTests.ts Replace __dirname usage with import.meta.url-based resolution for ESM.
test/omnisharp/omnisharpUnitTests/testAssets/mockHttpsServer.ts Bridge CommonJS-only dependency via createRequire(import.meta.url) and switch default import style.
test/omnisharp/omnisharpUnitTests/packages/zipInstaller.test.ts Update fs-extra import style for ESM compatibility.
test/omnisharp/omnisharpUnitTests/packages/packageFilterer.test.ts Rework fs mocking strategy for ESM Jest (unstable_mockModule + dynamic imports).
test/omnisharp/omnisharpUnitTests/logging/telemetryObserver.test.ts Update telemetry error-event assertions after removing deprecated errorProps usage.
test/omnisharp/omnisharpUnitTests/jest.config.mjs Migrate OmniSharp unit Jest config to .mjs + add unit VS Code mock setup.
test/omnisharp/omnisharpUnitTests/blazorWebAssemblyDetection.test.ts Update fs-extra import style for ESM compatibility.
test/omnisharp/omnisharpIntegrationTests/launchConfiguration.integration.test.ts Update fs-extra import style for ESM compatibility.
test/omnisharp/omnisharpIntegrationTests/jest.config.mjs Migrate OmniSharp integration Jest config to .mjs and shared project naming.
test/omnisharp/omnisharpIntegrationTests/index.ts Use shared Jest project names for OmniSharp integration runner.
test/lsptoolshost/unitTests/roslynLanguageClient.test.ts Convert mocks/imports to ESM-friendly unstable_mockModule + dynamic imports.
test/lsptoolshost/unitTests/migrateOptions.test.ts Rework fs mocking strategy for ESM Jest (unstable_mockModule + dynamic imports).
test/lsptoolshost/unitTests/jest.config.mjs Migrate LSP unit Jest config to .mjs + add unit VS Code mock setup.
test/lsptoolshost/integrationTests/testAssets/testAssets.ts Update fs-extra import style for ESM compatibility.
test/lsptoolshost/integrationTests/jest.config.mjs Migrate LSP integration Jest config to .mjs and shared project naming.
test/lsptoolshost/integrationTests/index.ts Use shared Jest project names for LSP integration runner.
test/lsptoolshost/artifactTests/vsix.test.ts Add stronger VSIX artifact assertions and update import styles for ESM.
test/lsptoolshost/artifactTests/jest.config.mjs Migrate artifact-tests Jest config to .mjs and shared project naming.
test/lsptoolshost/artifactTests/extensionBundle.test.ts Add artifact-level checks for ESM entry contract and signing coverage.
test/jestProjectNames.mjs Introduce centralized Jest project displayName constants (ESM).
test/jestProjectNames.d.mts Provide typed declaration for jestProjectNames in ESM contexts.
test/fakes.ts Update telemetry reporter fake for new sendTelemetryErrorEvent signature.
test/createTmpAsset.ts Update fs-extra usage to default import for ESM compatibility.
tasks/tests/testTasks.ts Switch test task orchestration to shared Jest project names (no per-project config exports).
tasks/tests/testHelpers.ts Update Jest invocation/config paths for .mjs and clarify ESM runner requirements.
tasks/tests/omnisharptestTasks.ts Switch OmniSharp test tasks to shared Jest project names.
tasks/projectPaths.ts Replace __dirname usage with import.meta.url-based resolution for ESM.
tasks/packaging/offlinePackagingTasks.ts Update fs-extra import style for ESM compatibility.
tasks/compilation/bundleAudit.mjs Add esbuild metafile-based audit enforcing bounded CommonJS require bridge.
src/shared/workspaceConfigurationProvider.ts Update fs-extra import style for ESM compatibility.
src/shared/utils.ts Update fs-extra import style for ESM compatibility.
src/shared/telemetryReporter.ts Update telemetry interface/signature and add ITelemetryReporterWithLevel for level-aware consumers.
src/shared/projectConfiguration.ts Adjust node-machine-id import style for ESM compatibility.
src/shared/processPicker.ts Update fs-extra import style for ESM compatibility.
src/shared/platform.ts Replace __dirname usage with import.meta.url-based resolution for ESM.
src/shared/dotnetConfigurationProvider.ts Update fs-extra import style for ESM compatibility.
src/shared/assets.ts Update fs-extra import style for ESM compatibility.
src/razor/src/blazorDebug/blazorDebugConfigurationProvider.ts Replace CommonJS require('path') import assignment with ESM-compatible import.
src/packageManager/zipInstaller.ts Update fs-extra usage to default import for ESM compatibility.
src/packageManager/downloadAndInstallPackages.ts Update fs-extra usage to default import for ESM compatibility.
src/omnisharp/observers/telemetryObserver.ts Remove deprecated errorProps callsite and document telemetry library behavior.
src/omnisharp/features/workspaceSymbolProvider.ts Formatting-only rewrite in diff (no functional change).
src/omnisharp/features/definitionMetadataDocumentProvider.ts Formatting-only rewrite in diff (no functional change).
src/omnisharp/engines/lspEngine.ts Update languageclient imports + feature-disabling logic without importing per-feature classes.
src/main.ts Switch telemetry import to ESM entry ({ TelemetryReporter }).
src/lsptoolshost/server/roslynLanguageServer.ts Switch telemetry typing + expose protocol2CodeConverter for downstream edit conversion.
src/lsptoolshost/extensions/builtInComponents.ts Replace __dirname usage with import.meta.url-based resolution for ESM.
src/lsptoolshost/diagnostics/nestedCodeAction.ts Use Roslyn language server converter instead of protocolConverter createConverter bridge.
src/lsptoolshost/diagnostics/fixAllCodeAction.ts Use Roslyn language server converter instead of protocolConverter createConverter bridge.
src/lsptoolshost/commands.ts Type telemetry reporter to shared interface instead of concrete telemetry class import.
src/lsptoolshost/activate.ts Replace __dirname usage with import.meta.url-based resolution and update telemetry typing.
src/activateRoslyn.ts Update telemetry typing to shared interface for Roslyn activation.
src/activateOmniSharp.ts Update telemetry typing to shared interface for OmniSharp activation.
package.json Mark package as ESM, switch main to .mjs, update scripts for ESM/tsx execution, bump telemetry + ts-jest deps.
package-lock.json Lockfile updates for telemetry bump, ts-jest bump, and dependency graph changes.
msbuild/signing/signJs/signJs.proj Extend JS signing inputs to include .mjs outputs.
jest.config.mjs Convert root Jest config to .mjs and point at project .mjs configs.
eslint.config.mjs Extend ignores for ESM build artifacts and VS Code test downloads.
esbuild.mjs Replace CommonJS esbuild script with ESM version + audits + telemetry ESM resolver plugin.
esbuild.js Remove old CommonJS esbuild entry point.
baseJestConfig.ts Remove old TypeScript base Jest config in favor of .mjs.
baseJestConfig.mjs Introduce ESM/CommonJS split base presets for Jest projects (unit vs integration).
.vscodeignore Update ignored build script name from esbuild.js to esbuild.mjs.
.vscode/launch.json Update debug configs for .mjs outputs and ESM test runner entrypoints + tsx loader usage.
mocks/vscode.ts Convert VS Code mock to ESM named exports for ESM Jest consumption.

Copilot's findings

  • Files reviewed: 76/80 changed files
  • Comments generated: 2

const fixAllEdit = await languageServer.protocol2CodeConverter.asWorkspaceEdit(response.edit);
if (!(await vscode.workspace.applyEdit(fixAllEdit))) {
const componentName = '[roslyn.client.nestedCodeAction]';
const errorMessage = 'Failed to make am edit for completion.';
Comment thread baseJestConfig.mjs
const jestTsconfigPath = fileURLToPath(new URL('./tsconfig.jest.json', import.meta.url));
const commonProjectConfig = {
testEnvironment: 'node',
transformIgnorePatterns: ['/dist/.+\\.js'],
@dibarbet

dibarbet commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

Closing - for now this doesn't provide a huge benefit, and mainly introduces new shims. We can re-evaluate once more of our base dependencies support native esm (like the vscode language client libraries).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants