Convert TypeScript sources to NodeNext ESM - #9617
Closed
dibarbet wants to merge 3 commits into
Closed
Conversation
dibarbet
force-pushed
the
dibarbet-esm-tooling-foundation
branch
from
August 4, 2026 00:42
97cc912 to
fd7f51c
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2af8a1f5-c78a-435b-805d-0328d6cd4106
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2af8a1f5-c78a-435b-805d-0328d6cd4106
dibarbet
force-pushed
the
dibarbet-esm-nodenext-conversion
branch
from
August 4, 2026 01:10
d9a568d to
61309d9
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Converts the extension’s TypeScript codebase and build/test tooling to an ESM-first setup (NodeNext), replacing CommonJS globals/patterns with import.meta.url-based equivalents while preserving Jest, esbuild bundling, and VS Code integration entry points.
Changes:
- Switch TypeScript typechecking to
module: Preserve/moduleResolution: BundlerwithnoEmit, and add dedicatedtsconfigfiles for Jest (CJS) and integration entry point emission (NodeNext). - Update tests/tooling to work in an ESM package (
type: module), including Jest config split for integration vs unit runs and updated runners/import specifiers. - Replace CommonJS-only patterns (
__dirname,require,module.exports) with ESM-compatible equivalents across tasks, tests, and runtime code.
Show a summary per file
| File | Description |
|---|---|
| wallaby.js | Convert Wallaby config to ESM export default. |
| tsconfig.json | Switch to ESM-preserving typecheck config (Preserve/Bundler, noEmit). |
| tsconfig.jest.json | Add CJS tsconfig override for Jest preset needing CommonJS. |
| tsconfig.integration.json | Add NodeNext-emitting config for VS Code integration test entry points. |
| test/vsCodeUnitFramework.ts | Ensure vscode virtual mock is set up for both Jest mock systems. |
| test/vsCodeFramework.ts | Add ESM-compatible unstable_mockModule for vscode virtual mock. |
| test/vsCodeEnvironment.ts | Export Jest environment class via ESM default export. |
| test/untrustedWorkspace/integrationTests/jest.config.mjs | Use the integration-oriented base Jest config. |
| test/untrustedWorkspace/integrationTests/index.ts | Use explicit .js specifier for compiled runner import edge. |
| test/runIntegrationTests.ts | Switch to default-imported Jest API for ESM runtime. |
| test/razor/razorTests/Microsoft.AspNetCore.Razor.VSCode.Grammar.Test/tests/infrastructure/tokenizedContentProvider.ts | Replace __dirname with import.meta.url-based pathing and adjust CJS interop imports. |
| test/razor/razorIntegrationTests/jest.config.mjs | Use the integration-oriented base Jest config. |
| test/razor/razorIntegrationTests/index.ts | Use explicit .js specifier for compiled runner import edge. |
| test/omnisharp/runFeatureTests.ts | Replace __dirname usage with import.meta.url-based directory resolution. |
| test/omnisharp/omnisharpUnitTests/testAssets/mockHttpsServer.ts | Use createRequire(import.meta.url) bridge for CJS-only dependency. |
| test/omnisharp/omnisharpUnitTests/packages/zipInstaller.test.ts | Update fs-extra import for ESM/CJS interop. |
| test/omnisharp/omnisharpUnitTests/packages/packageFilterer.test.ts | Convert fs mocking to unstable_mockModule + top-level await import(...). |
| test/omnisharp/omnisharpUnitTests/jest.config.mjs | Add unit test setup file for vscode mocking. |
| test/omnisharp/omnisharpUnitTests/blazorWebAssemblyDetection.test.ts | Update fs-extra import for ESM/CJS interop. |
| test/omnisharp/omnisharpIntegrationTests/launchConfiguration.integration.test.ts | Update fs-extra import for ESM/CJS interop. |
| test/omnisharp/omnisharpIntegrationTests/jest.config.mjs | Use the integration-oriented base Jest config. |
| test/omnisharp/omnisharpIntegrationTests/index.ts | Use explicit .js specifier for compiled runner import edge. |
| test/lsptoolshost/unitTests/roslynLanguageClient.test.ts | Convert mocks/imports to ESM-safe unstable_mockModule + dynamic imports. |
| test/lsptoolshost/unitTests/migrateOptions.test.ts | Convert fs mocking to unstable_mockModule + top-level await import(...). |
| test/lsptoolshost/unitTests/jest.config.mjs | Add unit test setup file for vscode mocking. |
| test/lsptoolshost/integrationTests/testAssets/testAssets.ts | Update fs-extra import for ESM/CJS interop. |
| test/lsptoolshost/integrationTests/jest.config.mjs | Use the integration-oriented base Jest config. |
| test/lsptoolshost/integrationTests/index.ts | Use explicit .js specifier for compiled runner import edge. |
| test/lsptoolshost/artifactTests/vsix.test.ts | Update fs-extra and glob imports for ESM/CJS interop. |
| test/createTmpAsset.ts | Avoid named import from fs-extra in ESM; use namespace/default import. |
| tasks/tests/testHelpers.ts | Switch to default-imported Jest API for ESM runtime. |
| tasks/projectPaths.ts | Replace __dirname usage with import.meta.url-based root resolution. |
| tasks/packaging/offlinePackagingTasks.ts | Update fs-extra import for ESM/CJS interop. |
| tasks/compilation/copyEsmSupportFiles.ts | Add build step to copy .mjs Jest support file into out/test. |
| src/shared/workspaceConfigurationProvider.ts | Update fs-extra import for ESM/CJS interop. |
| src/shared/utils.ts | Update fs-extra import for ESM/CJS interop. |
| src/shared/telemetryReporter.ts | Add telemetry reporter interface that includes telemetryLevel. |
| src/shared/projectConfiguration.ts | Adjust node-machine-id import shape for ESM/CJS interop. |
| src/shared/processPicker.ts | Update fs-extra import for ESM/CJS interop. |
| src/shared/platform.ts | Replace __dirname usage with import.meta.url-based directory resolution. |
| src/shared/dotnetConfigurationProvider.ts | Update fs-extra import for ESM/CJS interop. |
| src/shared/assets.ts | Update fs-extra import for ESM/CJS interop. |
| src/razor/src/blazorDebug/blazorDebugConfigurationProvider.ts | Replace require('path') pattern and adjust servicehub imports for ESM. |
| src/packageManager/zipInstaller.ts | Avoid named import from fs-extra in ESM; use namespace/default import. |
| src/packageManager/downloadAndInstallPackages.ts | Avoid named import from fs-extra in ESM; use namespace/default import. |
| src/omnisharp/features/workspaceSymbolProvider.ts | Formatting-only rewrite consistent with ESM conversion. |
| src/omnisharp/features/definitionMetadataDocumentProvider.ts | Formatting-only rewrite consistent with ESM conversion. |
| src/omnisharp/engines/lspEngine.ts | Refactor feature disabling to use request/notification method IDs (ESM-friendly imports). |
| src/main.ts | Adjust extension-telemetry import for CJS interop under ESM. |
| src/lsptoolshost/server/roslynLanguageServer.ts | Accept telemetry reporter interface and expose protocol converter for workspace edits. |
| src/lsptoolshost/extensions/builtInComponents.ts | Replace __dirname usage with import.meta.url-based directory resolution. |
| src/lsptoolshost/diagnostics/nestedCodeAction.ts | Use shared protocol converter for workspace edits (and contains a typo to fix). |
| src/lsptoolshost/diagnostics/fixAllCodeAction.ts | Use shared protocol converter for workspace edits. |
| src/lsptoolshost/commands.ts | Decouple from concrete telemetry reporter type via local interface. |
| src/lsptoolshost/activate.ts | Replace __dirname usage and switch to telemetry reporter interface type. |
| src/activateRoslyn.ts | Switch telemetry reporter parameter to interface with telemetry level. |
| src/activateOmniSharp.ts | Switch telemetry reporter parameter to interface type. |
| package.json | Mark package as ESM and update compile/test scripts for ESM + Jest VM modules. |
| eslint.config.mjs | Expand ignore list to include .vscode-test/**. |
| esbuild.mjs | Remove temporary bundled __filename/__dirname shims from banner. |
| baseJestConfig.mjs | Split base Jest config for unit (ESM) vs integration (CJS) environments. |
| .vscode/launch.json | Point integration test launch configs at explicit compiled index.js entry points. |
| mocks/vscode.ts | Convert vscode manual mock to ESM exports shape. |
Copilot's findings
Suppressed comments (1)
src/lsptoolshost/diagnostics/nestedCodeAction.ts:77
- Error message has a typo (“am edit”), and it’s inconsistent with the earlier log line that says “an edit”. This can make logs/telemetry harder to search and understand.
const componentName = '[roslyn.client.nestedCodeAction]';
const errorMessage = 'Failed to make am edit for completion.';
outputChannel.show();
- Files reviewed: 60/63 changed files
- Comments generated: 0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2af8a1f5-c78a-435b-805d-0328d6cd4106
Member
Author
|
Superseded by #9632 on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
rewriteRelativeImportExtensionswhile retainingmodule/moduleResolution: NodeNext.tssource extensions; TypeScript rewrites them to.jsthroughoutout/, including all directly loaded VS Code integration entries.mjssupport imports, Jest’s required transformed-.jssource mapper, runtime-correct CJS interop, existing output/copy behavior, and the bundle-levelcreateRequire(import.meta.url)bridge__filename/__dirnameshim now that all first-party usages useimport.meta.urlValidation
npm run compileDev.tsimports and correct.jsintegration-runner importsnpm run test:unit(11 suites, 514 tests, 350 snapshots)npm run packageDevandnode --check dist/extension.mjsnpm run test:integration:untrusted(1 test)npm run test:integration:csharp(21 suites, 73 passed, 3 skipped).tsimports, six intentional.mjsimports, zero extensionless/.js/.cjssource imports, and no__filename/__dirnamesource or banner definitions