Skip to content

Conversation

@Artmann
Copy link
Member

@Artmann Artmann commented Nov 20, 2025

Due to a vulnerability in the vega-lite package, we decided to upgrade it to the latest version. It's ESM only, which was the catalyst for migrating this entire project to ESM to avoid such problems in the future.

This also updates js-yaml to the latest version due to another vulnerability.

Remove the codecov package as we are using the CLI.

The PR for this is huge 😢 but the changes to the package.json file can be found here: https://github.com/deepnote/vscode-deepnote/pull/214/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519

Summary by CodeRabbit

  • Dependencies

    • Upgraded Vega stack and js-yaml; added esmock and esmock-related tooling.
  • Build System

    • Moved build and test tooling to ES Modules and added scripts to normalize ESM import paths; updated test runner/reporting configs.
  • Tests

    • Improved test harness, mocking, and ESM support; many unit/integration tests updated for stability and determinism.
  • Tooling

    • Adjusted linting rules, reporter configs, and spell-check vocabulary to better support ESM workflow and newer libraries.

✏️ Tip: You can customize this high-level summary in your review settings.

dependabot bot and others added 4 commits November 13, 2025 22:41
Bumps [vega-expression](https://github.com/vega/vega) to 5.2.1 and updates ancestor dependency [vega-lite](https://github.com/vega/vega-lite). These dependencies need to be updated together.


Updates `vega-expression` from 5.2.0 to 5.2.1
- [Release notes](https://github.com/vega/vega/releases)
- [Commits](https://github.com/vega/vega/commits)

Updates `vega-lite` from 5.23.0 to 6.4.1
- [Release notes](https://github.com/vega/vega-lite/releases)
- [Changelog](https://github.com/vega/vega-lite/blob/main/CHANGELOG.md)
- [Commits](vega/vega-lite@v5.23.0...v6.4.1)

---
updated-dependencies:
- dependency-name: vega-expression
  dependency-version: 5.2.1
  dependency-type: indirect
- dependency-name: vega-lite
  dependency-version: 6.4.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

📝 Walkthrough

Walkthrough

Migrates the codebase to ES modules and ESM tooling: adds "type":"module", converts CommonJS to import/export, updates relative imports to include .js, adds ESM utilities (getDirname/getFilename), and introduces test-friendly mutable wrappers (platformUtils, fileUtilsNodeUtils, uuidUtils, telemetryWrapper, tasClientWrapper). Updates build/test tooling (esbuild, Mocha configs, custom ESM loader), adds scripts to add/remove/fix .js extensions and directory/telemetry imports, introduces lazy crypto init and notebookUpdaterUtils indirection, and refactors many test files to use esmock and the new ESM-compatible patterns.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Developer
  participant Repo as TS Source
  participant BuildScripts as build/*.mjs
  participant Bundler as esbuild
  participant MochaCfg as build/.mocha*.json
  participant ESMLoader as build/mocha-esm-loader.js
  participant TestRunner as Mocha (ESM)
  participant Esmock as esmock
  participant VSCodeMock as src/test/vscode-mock
  participant Wrappers as runtime wrappers

  Developer->>Repo: convert modules to ESM (import/export, .js)
  Developer->>BuildScripts: add fix/remove .js & import-fix scripts
  BuildScripts->>Repo: rewrite import paths and index imports
  Developer->>Bundler: adapt esbuild for ESM (banner, externals)
  Bundler-->>Repo: build ESM bundles

  Developer->>MochaCfg: update Mocha to use ESM loader and node-options
  TestRunner->>ESMLoader: load tests with ESM loader
  ESMLoader->>VSCodeMock: intercept vscode & related specifiers -> provide mocks
  TestRunner->>Esmock: dynamically inject module mocks
  Esmock->>TestRunner: supply mocked modules to tests
  TestRunner->>Wrappers: tests stub runtime wrappers (platformUtils, uuidUtils, ...)
  Wrappers-->>TestRunner: allow test-time behavior overrides
  TestRunner-->>Developer: run results and reports
Loading

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main change: migrating to ESM and updating Vega libraries, matching the core objectives of the PR.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 20, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0%. Comparing base (1cc979d) to head (1d63873).

Additional details and impacted files
@@           Coverage Diff           @@
##            main   #214      +/-   ##
=======================================
- Coverage     73%      0     -74%     
=======================================
  Files        577      0     -577     
  Lines      47608      0   -47608     
  Branches    5591      0    -5591     
=======================================
- Hits       34856      0   -34856     
+ Misses     10922      0   -10922     
+ Partials    1830      0    -1830     

see 576 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 46

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (18)
src/kernels/raw/session/rawSessionConnection.node.ts (1)

50-56: Cache the dynamic require result to avoid repeated module loads.

The serverSettings getter performs a dynamic require on every access. Since the getter may be called multiple times during a session's lifetime, this results in repeated module lookups. Consider caching the result:

 export class RawSessionConnection implements Session.ISessionConnection {
     // ... other properties ...
+    private _cachedServerSettings?: ServerConnection.ISettings;

     get serverSettings(): ServerConnection.ISettings {
-        // We do not expect anyone to use this. Hence return a setting thats now expected to work, but at least compiles.
+        // We do not expect anyone to use this. Cached to avoid repeated module loads.
+        if (!this._cachedServerSettings) {
-        const jupyterLab = require('@jupyterlab/services') as typeof import('@jupyterlab/services'); // NOSONAR
-        return jupyterLab.ServerConnection.makeSettings({
+            const jupyterLab = require('@jupyterlab/services') as typeof import('@jupyterlab/services'); // NOSONAR
+            this._cachedServerSettings = jupyterLab.ServerConnection.makeSettings({
-            wsUrl: 'RAW'
+                wsUrl: 'RAW'
+            });
+        }
+        return this._cachedServerSettings;
     }

Also update the dispose() method to clear the cache:

 public dispose() {
     this._isDisposing = true;
+    this._cachedServerSettings = undefined;
     // ... rest of dispose logic ...
 }
src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (2)

524-583: Inconsistent with PR goal: Remove UI verification.

Line 582 asserts messageShown, verifying that showInformationMessage was called. Per the enriched summary, positive-path UI messaging expectations (e.g., save confirmations) should be removed. Only file write success and content should be verified.

Apply this diff:

         const saveUri = Uri.file('/tmp/test.csv');
         let fileWritten = false;
         let writtenContent = '';
-        let messageShown = false;
 
         // Mock fs.writeFile to track calls
         const mockFs = {
             writeFile: async (_uri: Uri, content: Uint8Array) => {
                 fileWritten = true;
                 writtenContent = new TextDecoder().decode(content);
             }
         };
         when(mockedVSCodeNamespaces.workspace.fs).thenReturn(mockFs as any);
 
         when(mockedVSCodeNamespaces.window.showSaveDialog(anything())).thenReturn(Promise.resolve(saveUri));
-        when(mockedVSCodeNamespaces.window.showInformationMessage(anything())).thenCall(() => {
-            messageShown = true;
-            return Promise.resolve();
-        });
 
         const message = { command: 'exportTable' as const, cellId: 'cell1' };
 
         await (controller as any).handleExportTable(editor, message);
 
         assert.isTrue(fileWritten);
         assert.strictEqual(writtenContent, 'id,name\n1,Alice\n2,Bob');
-        assert.isTrue(messageShown);

585-632: Missing verification: No assertion that error message was shown.

Comments state the method should show an error message (line 628), but the test doesn't verify showErrorMessage was called. The test passes if error handling is completely absent.

Apply this diff to verify error messaging:

         const message = { command: 'exportTable' as const, cellId: 'cell1' };
 
-        // The method should not throw, just show an error message to the user
-        await (controller as any).handleExportTable(editor, message);
-
-        // If we get here without throwing, the error handling worked correctly
+        let errorShown = false;
+        when(mockedVSCodeNamespaces.window.showErrorMessage(anything())).thenCall(() => {
+            errorShown = true;
+            return Promise.resolve();
+        });
+
+        await (controller as any).handleExportTable(editor, message);
+
+        assert.isTrue(errorShown, 'Error message should have been shown to user');
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (1)

299-347: Ensure skipped tests are tracked for completion.

The TODO comments clearly explain why tests are skipped—incomplete ZeroMQ mocking due to ESM migration. This is acceptable for a draft PR, but these tests must be re-enabled before merge.

Do you have a tracking issue for completing the ESM mocking and re-enabling these tests? If not, would you like me to help create one?

src/webviews/extension-side/plotting/plotViewer.node.ts (1)

68-86: Deferred promise is never resolved on finish

At line 78, ws.on('finish', () => deferred.resolve); just returns the resolver; it never calls it, so await deferred.promise will never complete and the PDF export can hang.

Use:

-    ws.on('finish', () => deferred.resolve);
+    ws.on('finish', () => deferred.resolve());

(or ws.on('finish', deferred.resolve); if resolve is a plain function).

src/platform/errors/index.ts (2)

10-25: Browser fetch error detection is now effectively disabled

Defining FetchError locally means !FetchError is always false, so isBrowserFetchError never becomes true and TypeError: Failed to fetch is no longer classified as a fetch error; this silently breaks telemetry classification in web contexts.

You can restore the intended behavior by keying solely off the error shape for the browser case and always treating FetchError as defined:

-    // In browsers, FetchError is undefined and the error we receive is a `TypeError` with message `Failed to fetch`.
-    const isBrowserFetchError = !FetchError && error?.name === 'TypeError' && error?.message === 'Failed to fetch';
-    const errorType = isBrowserFetchError ? TypeError : FetchError;
+    // In browsers, fetch failures typically surface as `TypeError` with message `Failed to fetch`.
+    const isBrowserFetchError = error?.name === 'TypeError' && error?.message === 'Failed to fetch';
+    const errorType = FetchError;
@@
-    // In the web we might receive other errors besides `TypeError: Failed to fetch`.
-    // In such cases, we should not try to compare the error type with `FetchError`, since it's not defined.
-    const isFetchError =
-        (isBrowserFetchError || FetchError !== undefined) && isErrorType(error, errorType);
+    // In the web we might receive other errors besides `TypeError: Failed to fetch`; only known shapes are classified as fetch errors.
+    const isFetchError = isErrorType(error, errorType) || isBrowserFetchError;

100-106: Replace console.error with centralized logger in isErrorType helper

The console.error call at line 104 violates the platform coding guideline requiring centralized logging. Add import { logger } from '../logging' and replace the call with logger.error().

+import { logger } from '../logging';
 
 function isErrorType<T>(error: Error, expectedType: Constructor<T>) {
     if (!expectedType) {
-        console.error('Error type is not defined', error);
+        logger.error('Error type is not defined', error);
         return false;
     }
src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (1)

256-358: Skipped createEnvironmentCommand test should be brought back before merging

Turning this into test.skip with only a FIXME effectively drops coverage for a complex flow (Python API wiring, quick pick, multiple input boxes, progress, environment creation, and success messaging). That’s a lot of behavior to leave untested indefinitely.

If ESM stubbing of the helpers is the blocker, consider:

  • Initializing a minimal real Python API instance for the test, or
  • Introducing an injectable abstraction around the helper calls that can be mocked without touching ESM exports.

Also, the final assertion now only checks that capturedOptions.pythonInterpreter is truthy. That’s safer than relying on a specific id, but you could still assert on high‑level invariants (e.g. URI or environment id chosen from mockResolvedEnvironment) without depending on helper internals.

I’d recommend:

  • Either fixing the setup so the test runs again, or splitting this into smaller tests that cover the public behavior you care about.
  • Optionally strengthening the interpreter assertion a bit while staying decoupled from helper implementation details.
src/test/web/customReporter.ts (1)

93-107: Fix dynamic fs-extra import – accessing methods on namespace object

Verified: await import('fs-extra') returns a namespace where fs-extra methods are on .default, not the top level. The current code will throw at runtime when the Desktop branch executes.

Apply the suggested guard pattern:

-            const fs = await import('fs-extra');
+            const ns = await import('fs-extra');
+            const fs = 'default' in ns ? (ns.default as typeof import('fs-extra')) : (ns as typeof import('fs-extra'));
             // eslint-disable-next-line local-rules/dont-use-fspath
             fs.ensureDirSync(logDir.fsPath);
             // eslint-disable-next-line local-rules/dont-use-fspath
             fs.writeFileSync(logFile.fsPath, JSON.stringify(messages));
src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (1)

246-345: Add GitHub issue tracking to skipped pandas-install tests

These two test.skip cases at lines 251 and 305 lack a GitHub issue ID to track re-enablement. The existing NOTE comments explain the esmock/vscode mocking conflict but provide no way to resurface this work. Add a comment like // TODO: Re-enable once #<issue-number> is resolved above each test.skip to link these to a tracking issue.

src/platform/interpreter/installer/poetryInstaller.unit.test.ts (1)

81-130: Tighten teardown: purge esmocked modules and avoid double sinon.restore()

You create two esmocked modules in setup but never purge them, and you also arrange for sinon.restore() via a disposable (Line 115) and call it again in teardown() (Line 125).

Consider:

  • Storing the esmocked modules (e.g., poetryNodeModule, poetryInstallerModule) in outer-scope variables and calling esmock.purge(...) on them in teardown() for deterministic module-cache cleanup.
  • Dropping either the disposable that calls sinon.restore() or the explicit sinon.restore() in teardown() to avoid redundant restores.

This will keep test isolation and cleanup behavior clearer.

After adjusting teardown, re-run this file’s tests (and any other suites using the same modules) to confirm there’s no cross-test leakage or order sensitivity.

src/test/vscode-mock.ts (1)

214-312: Fix invalid NotebookCellData assignment and optionally trim duplicates

Line 301 currently uses (mockedVSCode.NotebookCellData as any) = ..., which is not a valid assignment target. It should mirror the other casts by casting the object, not the property:

- (mockedVSCode.NotebookCellData as any) = vscodeMocks.vscMockExtHostedTypes.NotebookCellData;
+ (mockedVSCode as any).NotebookCellData = vscodeMocks.vscMockExtHostedTypes.NotebookCellData;

While you’re here, the double MarkdownString and repeated CompletionItemKind assignments further up look redundant unless they’re intentional.

src/platform/common/crypto.ts (1)

20-87: Keep computeHash’s default algorithm to avoid API breakage

The async crypto-provider init looks good, but computeHash no longer has a default algorithm. If any existing callers rely on computeHash(data) defaulting to 'SHA-256' (as before), this becomes a breaking change at compile-time or forces churn across many call sites.

You can preserve the old behavior while still supporting 'SHA-1' by restoring the default:

-export async function computeHash(data: string, algorithm: 'SHA-512' | 'SHA-256' | 'SHA-1'): Promise<string> {
+export async function computeHash(
+    data: string,
+    algorithm: 'SHA-512' | 'SHA-256' | 'SHA-1' = 'SHA-256'
+): Promise<string> {
build/webTestReporter.js (1)

30-39: Move screenshot-desktop import inside the try/catch

In captureScreenShot, the dynamic import('screenshot-desktop') happens before the try block, so a failure to load the module will reject the promise without being caught and can leave the HTTP request hanging.

Wrapping the import itself in the try keeps failures contained and still returns a 200/handled response:

-async function captureScreenShot(name, res) {
-    const screenshot = (await import('screenshot-desktop')).default;
-    fs.ensureDirSync(logsDir);
-    const filename = path.join(logsDir, name);
-    try {
-        await screenshot({ filename });
+async function captureScreenShot(name, res) {
+    fs.ensureDirSync(logsDir);
+    const filename = path.join(logsDir, name);
+    try {
+        const screenshot = (await import('screenshot-desktop')).default;
+        await screenshot({ filename });
src/interactive-window/editor-integration/codewatcher.unit.test.ts (1)

39-53: New initializeMockTextEditor helper + MockEditor‑based tests look correct; consider de‑duplicating the file name.

Wiring codeWatcher.setDocument(...) and mockedVSCodeNamespaces.window.activeTextEditor through initializeMockTextEditor makes the RunCell/RunCurrentCell/RunCurrentCellAndAdvance tests much closer to real editor behavior, and the fsPath string comparisons now match how CodeWatcher passes URIs into addCode. The only nit is that 'test.py'/fsPath is now hard‑coded both in the helper and in individual tests; if this ever changes, those two sources need to stay in sync, so a small optional improvement would be to let the helper accept an optional file name and reuse it in the expectations.

Also applies to: 406-408, 587-591, 596-598, 605-606, 910-913, 919-921, 928-931, 949-953, 958-960, 967-968

build/eslint-rules/index.js (1)

27-146: Custom rules look fine; confirm filename filters match your conventions.

The new dont-use-process, dont-use-fspath, and dont-use-filename rules are simple and safe, but their filename gating only exempts .node.ts (and .test.ts for the latter two). If you also have .spec.ts or other test suffixes that legitimately use fsPath/__dirname/__filename/process.env, you may want to extend the filename checks or handle that at the ESLint config level.

package.json (1)

2479-2479: Remove esmock from dependencies.

esmock is duplicated in both dependencies and devDependencies. Test mocking libraries typically belong only in devDependencies.

Apply this change:

 "dependencies": {
     ...
-    "esmock": "^2.7.3",
     ...
 },

Also applies to: 2651-2651

src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (1)

984-990: Update expected Vega schema to v6. The migration bumps Vega-Lite to v6, but the assertion still hardcodes the v5 schema URL. This will cause the test to fail once the production code emits the new schema and could hide real regressions. Please update the expected URL to the v6 schema.

-                assert.equal(
-                    content.spec.$schema,
-                    'https://vega.github.io/schema/vega-lite/v5.json',
-                    'Should have Vega-Lite schema'
-                );
+                assert.equal(
+                    content.spec.$schema,
+                    'https://vega.github.io/schema/vega-lite/v6.json',
+                    'Should have Vega-Lite schema'
+                );
♻️ Duplicate comments (1)
src/webviews/extension-side/dataviewer/dataViewerDependencyService.unit.test.ts (1)

252-284: Second skipped install-declined path has the same coverage gap

This test mirrors the previous one for the “user declines install” flow and is skipped for the same infrastructure reason; the same suggestion about introducing a VSCode wrapper (or tracking the unblock work) applies so this behavior doesn’t silently drift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc979d and 175218f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (138)
  • .eslintrc.cjs (3 hunks)
  • build/.mocha-multi-reporters.config (1 hunks)
  • build/.mocha.unittests.js.json (1 hunks)
  • build/.mocha.unittests.json (1 hunks)
  • build/.mocha.unittests.ts.json (1 hunks)
  • build/add-js-extensions.mjs (1 hunks)
  • build/ci/postInstall.js (4 hunks)
  • build/ci/scripts/spec_with_pid.js (2 hunks)
  • build/constants.js (1 hunks)
  • build/esbuild/build.ts (7 hunks)
  • build/esbuild/jquery.js (1 hunks)
  • build/eslint-rules/index.js (5 hunks)
  • build/fix-directory-imports.mjs (1 hunks)
  • build/fix-telemetry-imports.mjs (1 hunks)
  • build/launchWeb.js (1 hunks)
  • build/launchWebTest.js (1 hunks)
  • build/launchWebUtils.js (3 hunks)
  • build/mocha-esm-loader.js (1 hunks)
  • build/postDebugWebTest.js (1 hunks)
  • build/preDebugWebTest.js (2 hunks)
  • build/preLaunchWebTest.js (2 hunks)
  • build/remove-js-extensions.mjs (1 hunks)
  • build/tslint-rules/baseRuleWalker.js (1 hunks)
  • build/tslint-rules/messagesMustBeLocalizedRule.js (3 hunks)
  • build/util.js (1 hunks)
  • build/webTestReporter.js (5 hunks)
  • build/webpack/common.js (2 hunks)
  • build/webpack/pdfkit.js (1 hunks)
  • gulpfile.js (3 hunks)
  • package.json (3 hunks)
  • postcss.config.js (1 hunks)
  • src/extension.node.proxy.ts (1 hunks)
  • src/extension.node.ts (1 hunks)
  • src/interactive-window/editor-integration/codeGenerator.unit.test.ts (0 hunks)
  • src/interactive-window/editor-integration/codewatcher.ts (1 hunks)
  • src/interactive-window/editor-integration/codewatcher.unit.test.ts (4 hunks)
  • src/interactive-window/outputs/tracebackFormatter.ts (2 hunks)
  • src/interactive-window/shiftEnterBanner.unit.test.ts (6 hunks)
  • src/kernels/deepnote/deepnoteServerStarter.unit.test.ts (1 hunks)
  • src/kernels/deepnote/environments/deepnoteEnvironmentTreeItem.node.ts (1 hunks)
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (4 hunks)
  • src/kernels/execution/cellExecutionMessageHandler.ts (1 hunks)
  • src/kernels/execution/notebookUpdater.ts (2 hunks)
  • src/kernels/helpers.ts (1 hunks)
  • src/kernels/jupyter/jupyterUtils.ts (2 hunks)
  • src/kernels/jupyter/session/jupyterLabHelper.ts (2 hunks)
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts (5 hunks)
  • src/kernels/raw/finder/contributedKerneFinder.node.unit.test.ts (2 hunks)
  • src/kernels/raw/finder/jupyterPaths.node.unit.test.ts (5 hunks)
  • src/kernels/raw/launcher/kernelLauncher.unit.test.ts (1 hunks)
  • src/kernels/raw/launcher/kernelProcess.node.ts (1 hunks)
  • src/kernels/raw/launcher/kernelProcess.node.unit.test.ts (1 hunks)
  • src/kernels/raw/session/rawKernelConnection.node.ts (2 hunks)
  • src/kernels/raw/session/rawSessionConnection.node.ts (2 hunks)
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (6 hunks)
  • src/kernels/raw/session/zeromq.node.ts (1 hunks)
  • src/notebooks/controllers/ipywidgets/message/ipyWidgetMessageDispatcher.ts (3 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.unit.test.ts (1 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/cdnWidgetScriptSourceProvider.unit.test.ts (2 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/ipyWidgetScriptSource.ts (2 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/localWidgetScriptSourceProvider.unit.test.ts (1 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/nbExtensionsPathProvider.unit.test.ts (1 hunks)
  • src/notebooks/controllers/vscodeNotebookController.unit.test.ts (5 hunks)
  • src/notebooks/deepnote/deepnoteDataConverter.ts (3 hunks)
  • src/notebooks/deepnote/deepnoteExplorerView.ts (5 hunks)
  • src/notebooks/deepnote/deepnoteExplorerView.unit.test.ts (11 hunks)
  • src/notebooks/deepnote/deepnoteNotebookCommandListener.ts (5 hunks)
  • src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (17 hunks)
  • src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (3 hunks)
  • src/notebooks/deepnote/deepnoteTreeDataProvider.unit.test.ts (1 hunks)
  • src/notebooks/deepnote/deepnoteTreeItem.ts (2 hunks)
  • src/notebooks/deepnote/openInDeepnoteHandler.node.unit.test.ts (9 hunks)
  • src/notebooks/notebookEnvironmentService.node.ts (2 hunks)
  • src/platform/common/crypto.ts (2 hunks)
  • src/platform/common/esmUtils.node.ts (1 hunks)
  • src/platform/common/experiments/service.ts (3 hunks)
  • src/platform/common/experiments/service.unit.test.ts (6 hunks)
  • src/platform/common/experiments/tasClientWrapper.ts (1 hunks)
  • src/platform/common/experiments/telemetry.node.ts (3 hunks)
  • src/platform/common/experiments/telemetry.unit.test.ts (2 hunks)
  • src/platform/common/platform/fileSystem.node.unit.test.ts (1 hunks)
  • src/platform/common/platform/fileUtils.node.ts (2 hunks)
  • src/platform/common/platform/fileUtils.ts (1 hunks)
  • src/platform/common/platform/fs-paths.ts (1 hunks)
  • src/platform/common/utils/platform.node.ts (1 hunks)
  • src/platform/common/utils/platform.ts (2 hunks)
  • src/platform/common/uuid.ts (2 hunks)
  • src/platform/common/variables/customEnvironmentVariablesProvider.node.unit.test.ts (3 hunks)
  • src/platform/common/variables/systemVariables.node.ts (2 hunks)
  • src/platform/constants.node.ts (1 hunks)
  • src/platform/constants.ts (1 hunks)
  • src/platform/errors/index.ts (1 hunks)
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts (2 hunks)
  • src/platform/interpreter/installer/pipenv.node.ts (4 hunks)
  • src/platform/interpreter/installer/pipenv.unit.test.ts (2 hunks)
  • src/platform/interpreter/installer/poetry.unit.test.ts (8 hunks)
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts (3 hunks)
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (1 hunks)
  • src/platform/ioc/reflectMetadata.ts (1 hunks)
  • src/platform/logging/consoleLogger.ts (1 hunks)
  • src/platform/logging/outputChannelLogger.ts (1 hunks)
  • src/platform/telemetry/index.ts (3 hunks)
  • src/platform/telemetry/wrapper.ts (1 hunks)
  • src/standalone/intellisense/completionDocumentationFormatter.node.unit.test.ts (1 hunks)
  • src/standalone/intellisense/resolveCompletionItem.unit.test.ts (7 hunks)
  • src/test/analysisEngineTest.node.ts (1 hunks)
  • src/test/common.node.ts (4 hunks)
  • src/test/common/asyncDump.ts (1 hunks)
  • src/test/common/variables/envVarsService.vscode.test.ts (1 hunks)
  • src/test/constants.node.ts (1 hunks)
  • src/test/constants.ts (1 hunks)
  • src/test/coverage.node.ts (1 hunks)
  • src/test/datascience/.env (1 hunks)
  • src/test/datascience/data-viewing/showInDataViewerPythonInterpreter.vscode.test.ts (0 hunks)
  • src/test/datascience/export/exportUtil.unit.test.ts (1 hunks)
  • src/test/datascience/interactiveWindow.vscode.common.test.ts (4 hunks)
  • src/test/debuggerTest.node.ts (1 hunks)
  • src/test/extension.serviceRegistry.vscode.test.ts (1 hunks)
  • src/test/index.node.ts (6 hunks)
  • src/test/interpreters/condaService.node.ts (1 hunks)
  • src/test/interpreters/condaService.node.unit.test.ts (1 hunks)
  • src/test/pythonEnvironments/constants.ts (1 hunks)
  • src/test/smokeTest.node.ts (1 hunks)
  • src/test/standardTest.node.ts (1 hunks)
  • src/test/testHooks.node.ts (1 hunks)
  • src/test/testRunner.ts (2 hunks)
  • src/test/unittests.ts (2 hunks)
  • src/test/vscode-mock.ts (4 hunks)
  • src/test/web/customReporter.ts (9 hunks)
  • src/test/web/index.ts (1 hunks)
  • src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (4 hunks)
  • src/webviews/extension-side/dataviewer/dataViewerDependencyService.unit.test.ts (4 hunks)
  • src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (7 hunks)
  • src/webviews/extension-side/ipywidgets/rendererComms.ts (2 hunks)
  • src/webviews/extension-side/plotting/plotViewer.node.ts (1 hunks)
  • tailwind.config.js (1 hunks)
  • tsconfig.base.json (1 hunks)
  • tsconfig.tsbuildinfo (1 hunks)
💤 Files with no reviewable changes (2)
  • src/interactive-window/editor-integration/codeGenerator.unit.test.ts
  • src/test/datascience/data-viewing/showInDataViewerPythonInterpreter.vscode.test.ts
🧰 Additional context used
📓 Path-based instructions (20)
**/*.{test,spec}.ts

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

In unit tests, when a mock is returned from a promise, ensure the mocked instance has an undefined then property to avoid hanging tests

Files:

  • src/test/common/variables/envVarsService.vscode.test.ts
  • src/test/interpreters/condaService.node.unit.test.ts
  • src/kernels/raw/finder/contributedKerneFinder.node.unit.test.ts
  • src/standalone/intellisense/completionDocumentationFormatter.node.unit.test.ts
  • src/kernels/raw/launcher/kernelLauncher.unit.test.ts
  • src/platform/interpreter/installer/pipenv.unit.test.ts
  • src/platform/common/platform/fileSystem.node.unit.test.ts
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.unit.test.ts
  • src/test/datascience/interactiveWindow.vscode.common.test.ts
  • src/kernels/raw/finder/jupyterPaths.node.unit.test.ts
  • src/platform/common/experiments/telemetry.unit.test.ts
  • src/notebooks/deepnote/deepnoteSerializer.unit.test.ts
  • src/kernels/raw/launcher/kernelProcess.node.unit.test.ts
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/localWidgetScriptSourceProvider.unit.test.ts
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts
  • src/notebooks/controllers/vscodeNotebookController.unit.test.ts
  • src/notebooks/deepnote/deepnoteTreeDataProvider.unit.test.ts
  • src/platform/common/variables/customEnvironmentVariablesProvider.node.unit.test.ts
  • src/platform/interpreter/installer/poetry.unit.test.ts
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts
  • src/notebooks/deepnote/deepnoteExplorerView.unit.test.ts
  • src/kernels/deepnote/deepnoteServerStarter.unit.test.ts
  • src/test/extension.serviceRegistry.vscode.test.ts
  • src/test/datascience/export/exportUtil.unit.test.ts
  • src/webviews/extension-side/dataframe/dataframeController.unit.test.ts
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/cdnWidgetScriptSourceProvider.unit.test.ts
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/nbExtensionsPathProvider.unit.test.ts
  • src/notebooks/deepnote/openInDeepnoteHandler.node.unit.test.ts
  • src/webviews/extension-side/dataviewer/dataViewerDependencyService.unit.test.ts
  • src/interactive-window/editor-integration/codewatcher.unit.test.ts
  • src/platform/common/experiments/service.unit.test.ts
  • src/interactive-window/shiftEnterBanner.unit.test.ts
  • src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts
  • src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
  • src/standalone/intellisense/resolveCompletionItem.unit.test.ts
src/platform/**/ioc/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Register platform services in the IoC container using ServiceManager (e.g., serviceManager.addSingleton(Token, Impl)) within a registerTypes function

Files:

  • src/platform/ioc/reflectMetadata.ts
src/platform/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

src/platform/**/*.ts: Use Inversify decorators for DI: annotate classes with @Injectable() and inject dependencies with @Inject(Token)
Use the centralized logger (import { logger } from '../platform/logging') instead of console.log for application logging

Files:

  • src/platform/ioc/reflectMetadata.ts
  • src/platform/common/experiments/telemetry.node.ts
  • src/platform/logging/consoleLogger.ts
  • src/platform/telemetry/wrapper.ts
  • src/platform/common/esmUtils.node.ts
  • src/platform/interpreter/installer/pipenv.unit.test.ts
  • src/platform/common/platform/fileSystem.node.unit.test.ts
  • src/platform/common/experiments/tasClientWrapper.ts
  • src/platform/common/experiments/telemetry.unit.test.ts
  • src/platform/common/platform/fs-paths.ts
  • src/platform/interpreter/installer/pipenv.node.ts
  • src/platform/common/platform/fileUtils.node.ts
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts
  • src/platform/errors/index.ts
  • src/platform/common/variables/customEnvironmentVariablesProvider.node.unit.test.ts
  • src/platform/common/uuid.ts
  • src/platform/interpreter/installer/poetry.unit.test.ts
  • src/platform/common/utils/platform.ts
  • src/platform/logging/outputChannelLogger.ts
  • src/platform/common/variables/systemVariables.node.ts
  • src/platform/constants.ts
  • src/platform/common/platform/fileUtils.ts
  • src/platform/common/utils/platform.node.ts
  • src/platform/telemetry/index.ts
  • src/platform/common/experiments/service.ts
  • src/platform/common/experiments/service.unit.test.ts
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts
  • src/platform/constants.node.ts
  • src/platform/common/crypto.ts
src/kernels/**/finder/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

src/kernels/**/finder/**/*.ts: All finder implementations must implement the IContributedKernelFinder interface
Finder implementations should use caching to avoid redundant discovery work
Activate finder scans lazily (only when needed) to reduce startup cost

Files:

  • src/kernels/raw/finder/contributedKerneFinder.node.unit.test.ts
  • src/kernels/raw/finder/jupyterPaths.node.unit.test.ts
src/kernels/raw/finder/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Raw kernel discovery must scan local kernel specs and Python environments

Files:

  • src/kernels/raw/finder/contributedKerneFinder.node.unit.test.ts
  • src/kernels/raw/finder/jupyterPaths.node.unit.test.ts
src/kernels/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

src/kernels/**/*.ts: Use event-driven updates (EventEmitter) for state changes
Monitor and dispose pending promises to prevent leaks during teardown
Use WeakRef/weak references for notebook/object backreferences to avoid memory leaks
Respect CancellationToken in all async operations

Files:

  • src/kernels/raw/finder/contributedKerneFinder.node.unit.test.ts
  • src/kernels/raw/session/zeromq.node.ts
  • src/kernels/raw/launcher/kernelLauncher.unit.test.ts
  • src/kernels/jupyter/jupyterUtils.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
  • src/kernels/raw/finder/jupyterPaths.node.unit.test.ts
  • src/kernels/raw/launcher/kernelProcess.node.unit.test.ts
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts
  • src/kernels/helpers.ts
  • src/kernels/deepnote/deepnoteServerStarter.unit.test.ts
  • src/kernels/execution/cellExecutionMessageHandler.ts
  • src/kernels/raw/launcher/kernelProcess.node.ts
  • src/kernels/execution/notebookUpdater.ts
  • src/kernels/deepnote/environments/deepnoteEnvironmentTreeItem.node.ts
  • src/kernels/jupyter/session/jupyterLabHelper.ts
  • src/kernels/raw/session/rawKernelConnection.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/kernels/{jupyter,raw}/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

All session implementations must conform to IKernelSession

Files:

  • src/kernels/raw/session/zeromq.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
  • src/kernels/jupyter/session/jupyterLabHelper.ts
  • src/kernels/raw/session/rawKernelConnection.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/kernels/raw/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Raw sessions must use ZeroMQ socket communication

Files:

  • src/kernels/raw/session/zeromq.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
  • src/kernels/raw/session/rawKernelConnection.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/interactive-window/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/interactiveWindow.instructions.md)

src/interactive-window/**/*.ts: Consider platform differences (Desktop/Node vs Web) for features and fallbacks when implementing functionality
Use dependency injection to keep components testable
Respect CancellationToken in async operations and support cancellation in long-running tasks
Use EventEmitter for event-driven updates and ensure proper disposal/cleanup of listeners to prevent leaks
Monitor and track promises/async operations to ensure proper cleanup and avoid dangling work on dispose
Add unit and integration tests for new features and modifications; include performance and cross-platform test coverage

Files:

  • src/interactive-window/editor-integration/codewatcher.ts
  • src/interactive-window/outputs/tracebackFormatter.ts
  • src/interactive-window/editor-integration/codewatcher.unit.test.ts
  • src/interactive-window/shiftEnterBanner.unit.test.ts
src/interactive-window/editor-integration/**

📄 CodeRabbit inference engine (.github/instructions/interactiveWindow.instructions.md)

Verify cell detection across marker formats and ensure accurate source mapping when editor integration changes

Files:

  • src/interactive-window/editor-integration/codewatcher.ts
  • src/interactive-window/editor-integration/codewatcher.unit.test.ts
src/platform/**/*.node.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

src/platform/**/*.node.ts: Provide Node.js-specific implementations in .node.ts files (e.g., FileSystem with fs-extra, PlatformService with OS detection)
Desktop implementations may use Node capabilities (fs-extra, process spawning, native modules) consistent with their responsibilities

Files:

  • src/platform/common/experiments/telemetry.node.ts
  • src/platform/common/esmUtils.node.ts
  • src/platform/interpreter/installer/pipenv.node.ts
  • src/platform/common/platform/fileUtils.node.ts
  • src/platform/common/variables/systemVariables.node.ts
  • src/platform/common/utils/platform.node.ts
  • src/platform/constants.node.ts
src/platform/logging/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Implement logging using OutputChannelLogger/ConsoleLogger and honor LogLevel; ensure PII scrubbing in log output

Files:

  • src/platform/logging/consoleLogger.ts
  • src/platform/logging/outputChannelLogger.ts
src/platform/telemetry/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Send telemetry via platform telemetry utilities and use helpers.ts for safe hashing/anonymization

Files:

  • src/platform/telemetry/wrapper.ts
  • src/platform/telemetry/index.ts
src/kernels/raw/launcher/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Raw launcher must spawn kernel processes and manage ports/connection files

Files:

  • src/kernels/raw/launcher/kernelLauncher.unit.test.ts
  • src/kernels/raw/launcher/kernelProcess.node.unit.test.ts
  • src/kernels/raw/launcher/kernelProcess.node.ts
src/kernels/jupyter/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel-jupyter.instructions.md)

src/kernels/jupyter/**/*.ts: Avoid blocking operations; use async/await consistently for asynchronous flows
Avoid shared global state for services; prefer instance-scoped or injected dependencies

Files:

  • src/kernels/jupyter/jupyterUtils.ts
  • src/kernels/jupyter/session/jupyterLabHelper.ts
src/platform/common/platform/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Expose file system operations through IFileSystem/IFileSystemNode and platform data via IPlatformService instead of direct APIs

Files:

  • src/platform/common/platform/fileSystem.node.unit.test.ts
  • src/platform/common/platform/fs-paths.ts
  • src/platform/common/platform/fileUtils.node.ts
  • src/platform/common/platform/fileUtils.ts
src/kernels/execution/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Notebook-level execution must enqueue cells via CellExecutionQueue and manage per-cell lifecycles through CellExecution

Files:

  • src/kernels/execution/cellExecutionMessageHandler.ts
  • src/kernels/execution/notebookUpdater.ts
src/kernels/jupyter/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel-jupyter.instructions.md)

src/kernels/jupyter/session/**/*.ts: Always use JupyterLab manager classes (SessionManager, KernelManager, KernelSpecManager, ContentsManager) for lifecycle management instead of creating services directly
Call dispose() on all @jupyterlab/services objects (managers, sessions, kernels, contents) to prevent resource leaks

Jupyter sessions must use HTTP/WebSocket communication

Files:

  • src/kernels/jupyter/session/jupyterLabHelper.ts
src/kernels/jupyter/{connection,session}/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel-jupyter.instructions.md)

Reuse a single ServerConnection.ISettings instance for a given server to enable connection sharing and caching

Files:

  • src/kernels/jupyter/session/jupyterLabHelper.ts
src/kernels/jupyter/{connection,launcher,session,finder}/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel-jupyter.instructions.md)

src/kernels/jupyter/{connection,launcher,session,finder}/**/*.ts: Wrap all @jupyterlab/services calls and network interactions with robust error handling and meaningful error types
Support cancellation via CancellationToken (or equivalent) for long-running async operations (network calls, startup waits)
Implement automatic retry with exponential backoff for transient connection/session errors
Provide fallbacks or graceful degradation when services are unavailable and surface actionable, user-friendly error messages

Files:

  • src/kernels/jupyter/session/jupyterLabHelper.ts
🧬 Code graph analysis (67)
src/test/common/variables/envVarsService.vscode.test.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/common/experiments/telemetry.node.ts (1)
src/platform/telemetry/wrapper.ts (1)
  • telemetryWrapper (11-14)
src/kernels/raw/launcher/kernelLauncher.unit.test.ts (2)
build/webTestReporter.js (1)
  • __dirname (20-20)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/interpreter/installer/pipenv.unit.test.ts (1)
src/platform/common/platform/fileUtils.node.ts (1)
  • pathExists (53-53)
src/kernels/jupyter/jupyterUtils.ts (2)
src/webviews/webview-side/ipywidgets/kernel/kernel.ts (1)
  • serverSettings (39-41)
src/kernels/common/baseJupyterSessionConnection.ts (1)
  • serverSettings (32-34)
src/extension.node.proxy.ts (3)
src/extension.node.ts (1)
  • activate (78-130)
src/test/web/index.ts (1)
  • activate (43-94)
src/extension.web.ts (1)
  • activate (80-120)
src/notebooks/deepnote/deepnoteExplorerView.ts (1)
src/platform/common/uuid.ts (1)
  • uuidUtils (64-66)
src/test/standardTest.node.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/kernels/raw/finder/jupyterPaths.node.unit.test.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getFilename (22-24)
src/platform/common/experiments/telemetry.unit.test.ts (2)
src/platform/common/experiments/telemetry.node.ts (1)
  • ExperimentationTelemetry (10-27)
src/platform/telemetry/wrapper.ts (1)
  • telemetryWrapper (11-14)
src/test/constants.node.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/test/index.node.ts (2)
src/test/coverage.node.ts (1)
  • setupCoverage (10-41)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (1)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
src/test/testHooks.node.ts (1)
src/platform/common/constants.ts (1)
  • AppinsightsKey (30-30)
src/test/unittests.ts (2)
src/test/vscode-mock.ts (1)
  • mockedVSCode (14-14)
src/test/coverage.node.ts (1)
  • setupCoverage (10-41)
src/kernels/raw/launcher/kernelProcess.node.unit.test.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/test/testRunner.ts (2)
build/ci/postInstall.js (1)
  • __dirname (15-15)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/interpreter/installer/pipenv.node.ts (2)
src/platform/common/platform/fileUtils.ts (1)
  • fileUtilsCommonUtils (16-18)
src/platform/common/platform/fileUtils.node.ts (1)
  • fileUtilsNodeUtils (47-50)
src/test/debuggerTest.node.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/test/smokeTest.node.ts (3)
build/webTestReporter.js (1)
  • __dirname (20-20)
gulpfile.js (1)
  • __dirname (26-26)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
build/esbuild/build.ts (4)
build/ci/postInstall.js (2)
  • __filename (14-14)
  • __dirname (15-15)
build/launchWebUtils.js (2)
  • __filename (15-15)
  • __dirname (16-16)
build/preLaunchWebTest.js (2)
  • __filename (10-10)
  • __dirname (11-11)
gulpfile.js (2)
  • __filename (25-25)
  • __dirname (26-26)
src/notebooks/deepnote/deepnoteNotebookCommandListener.ts (1)
src/kernels/execution/notebookUpdater.ts (1)
  • notebookUpdaterUtils (62-65)
src/test/vscode-mock.ts (3)
src/notebooks/controllers/notebookIPyWidgetCoordinator.ts (1)
  • onDidCloseNotebookDocument (173-180)
src/test/datascience/notebook/controllerPreferredService.ts (1)
  • onDidOpenNotebookDocument (370-393)
src/standalone/recommendation/extensionRecommendation.node.ts (1)
  • onDidOpenNotebookDocument (64-72)
src/notebooks/controllers/ipywidgets/scriptSourceProvider/localWidgetScriptSourceProvider.unit.test.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
build/tslint-rules/baseRuleWalker.js (2)
build/constants.js (2)
  • ExtensionRootDir (6-6)
  • ExtensionRootDir (6-6)
build/util.js (2)
  • ExtensionRootDir (12-12)
  • ExtensionRootDir (12-12)
src/platform/interpreter/installer/poetryInstaller.unit.test.ts (3)
src/platform/common/platform/fileUtils.node.ts (4)
  • shellExecute (21-26)
  • pathExistsSync (34-36)
  • readFileSync (42-44)
  • getPythonSetting (62-66)
src/platform/common/process/types.node.ts (2)
  • ShellOptions (40-40)
  • ExecutionResult (42-45)
src/platform/interpreter/installer/moduleInstaller.node.ts (1)
  • ExecutionInstallArgs (30-35)
src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (1)
src/platform/interpreter/installer/moduleInstaller.node.ts (1)
  • ExecutionInstallArgs (30-35)
src/notebooks/controllers/vscodeNotebookController.unit.test.ts (2)
src/test/vscode-mock.ts (2)
  • mockedVSCodeNamespaces (15-15)
  • mockedVSCode (14-14)
src/test/mocks/vsc/index.ts (1)
  • EventEmitter (65-89)
src/test/pythonEnvironments/constants.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/common/variables/customEnvironmentVariablesProvider.node.unit.test.ts (1)
src/platform/logging/index.ts (1)
  • logger (35-48)
src/platform/interpreter/installer/poetry.unit.test.ts (5)
src/test/pythonEnvironments/constants.ts (1)
  • TEST_LAYOUT_ROOT (11-11)
src/platform/interpreter/installer/poetry.node.ts (2)
  • isPoetryEnvironment (83-91)
  • Poetry (97-297)
src/platform/common/platform/fileUtils.node.ts (5)
  • shellExecute (21-26)
  • getPythonSetting (62-66)
  • pathExistsSync (34-36)
  • readFileSync (42-44)
  • isVirtualenvEnvironment (95-106)
src/platform/common/utils/platform.ts (1)
  • getOSType (35-35)
src/platform/common/utils/platform.node.ts (1)
  • getUserHomeDir (30-38)
build/preLaunchWebTest.js (3)
build/launchWebUtils.js (2)
  • __filename (15-15)
  • __dirname (16-16)
gulpfile.js (2)
  • __filename (25-25)
  • __dirname (26-26)
src/test/datascience/jupyterServer.node.ts (1)
  • startJupyter (139-154)
gulpfile.js (1)
build/ci/postInstall.js (3)
  • __filename (14-14)
  • __dirname (15-15)
  • packageLock (141-141)
build/tslint-rules/messagesMustBeLocalizedRule.js (2)
build/util.js (1)
  • getListOfFiles (14-24)
build/tslint-rules/baseRuleWalker.js (1)
  • BaseRuleWalker (8-19)
src/notebooks/deepnote/deepnoteTreeItem.ts (2)
src/platform/deepnote/deepnoteTypes.ts (2)
  • DeepnoteProject (12-12)
  • DeepnoteNotebook (18-18)
src/test/mocks/vsc/extHostedTypes.ts (1)
  • ThemeIcon (2094-2104)
build/webTestReporter.js (2)
gulpfile.js (2)
  • __filename (25-25)
  • __dirname (26-26)
src/test/common.node.ts (1)
  • captureScreenShot (188-205)
src/platform/common/utils/platform.ts (1)
src/platform/vscode-path/platform.ts (1)
  • platform (164-164)
src/notebooks/deepnote/deepnoteDataConverter.ts (1)
src/platform/common/uuid.ts (1)
  • uuidUtils (64-66)
src/kernels/deepnote/environments/deepnoteEnvironmentTreeItem.node.ts (1)
src/test/mocks/vsc/extHostedTypes.ts (1)
  • ThemeIcon (2094-2104)
src/test/extension.serviceRegistry.vscode.test.ts (3)
build/webTestReporter.js (1)
  • __dirname (20-20)
.vscode-test.mjs (1)
  • __dirname (9-9)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/notebooks/notebookEnvironmentService.node.ts (2)
src/platform/common/utils/encoder.ts (1)
  • toPythonSafePath (4-6)
src/platform/common/esmUtils.node.ts (1)
  • getFilename (22-24)
build/ci/postInstall.js (1)
build/webpack/common.js (3)
  • getBundleConfiguration (42-54)
  • bundleConfiguration (29-36)
  • bundleConfiguration (29-36)
src/test/common.node.ts (2)
build/webTestReporter.js (2)
  • screenshot (31-31)
  • filename (33-33)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/common/variables/systemVariables.node.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/test/analysisEngineTest.node.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
build/launchWebUtils.js (2)
build/preLaunchWebTest.js (2)
  • __filename (10-10)
  • __dirname (11-11)
gulpfile.js (2)
  • __filename (25-25)
  • __dirname (26-26)
src/platform/common/platform/fileUtils.ts (2)
src/platform/common/platform/fileUtils.node.ts (1)
  • arePathsSame (10-10)
src/platform/common/platform/fileSystem.ts (1)
  • arePathsSame (26-28)
build/fix-directory-imports.mjs (1)
build/fix-telemetry-imports.mjs (1)
  • pattern (41-41)
src/platform/common/utils/platform.node.ts (1)
src/platform/common/variables/types.ts (1)
  • EnvironmentVariables (8-8)
src/platform/telemetry/index.ts (1)
src/platform/common/constants.ts (1)
  • AppinsightsKey (30-30)
src/platform/common/experiments/service.ts (1)
src/platform/common/experiments/tasClientWrapper.ts (1)
  • tasClientWrapper (8-10)
src/notebooks/controllers/ipywidgets/scriptSourceProvider/nbExtensionsPathProvider.unit.test.ts (1)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
build/add-js-extensions.mjs (1)
build/fix-telemetry-imports.mjs (1)
  • pattern (41-41)
src/notebooks/deepnote/openInDeepnoteHandler.node.unit.test.ts (2)
src/test/vscode-mock.ts (2)
  • resetVSCodeMocks (57-205)
  • mockedVSCodeNamespaces (15-15)
src/notebooks/deepnote/importClient.node.ts (1)
  • MAX_FILE_SIZE (28-28)
src/webviews/extension-side/dataviewer/dataViewerDependencyService.unit.test.ts (2)
src/webviews/extension-side/dataviewer/kernelDataViewerDependencyImplementation.ts (1)
  • kernelGetPandasVersion (16-16)
src/test/vscode-mock.ts (2)
  • mockedVSCodeNamespaces (15-15)
  • mockedVSCode (14-14)
src/interactive-window/editor-integration/codewatcher.unit.test.ts (1)
src/test/mocks/vsc/extHostedTypes.ts (1)
  • Selection (485-559)
src/platform/common/experiments/service.unit.test.ts (2)
src/platform/common/experiments/tasClientWrapper.ts (1)
  • tasClientWrapper (8-10)
src/platform/telemetry/wrapper.ts (1)
  • telemetryWrapper (11-14)
src/interactive-window/shiftEnterBanner.unit.test.ts (1)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (1)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts (1)
src/platform/interpreter/installer/pipenv.node.ts (1)
  • isPipenvEnvironmentRelatedToFolder (104-118)
build/constants.js (2)
build/util.js (2)
  • ExtensionRootDir (12-12)
  • ExtensionRootDir (12-12)
gulpfile.js (1)
  • isCI (28-28)
build/remove-js-extensions.mjs (1)
build/fix-telemetry-imports.mjs (1)
  • pattern (41-41)
src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (2)
src/webviews/extension-side/dataviewer/kernelDataViewerDependencyImplementation.ts (1)
  • kernelGetPandasVersion (16-16)
src/test/vscode-mock.ts (2)
  • mockedVSCodeNamespaces (15-15)
  • mockedVSCode (14-14)
src/platform/constants.node.ts (2)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/platform/constants.ts (1)
  • isPreReleaseVersion (8-12)
build/util.js (2)
gulpfile.js (2)
  • __filename (25-25)
  • __dirname (26-26)
build/constants.js (2)
  • ExtensionRootDir (6-6)
  • ExtensionRootDir (6-6)
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (2)
build/ci/postInstall.js (1)
  • __dirname (15-15)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/standalone/intellisense/resolveCompletionItem.unit.test.ts (3)
src/standalone/intellisense/kernelCompletionProvider.ts (3)
  • resolveCompletionItem (311-335)
  • resolveCompletionItem (484-487)
  • dispose (459-462)
src/standalone/intellisense/resolveCompletionItem.ts (2)
  • resolveCompletionItem (40-90)
  • maxPendingKernelRequests (28-28)
src/platform/common/utils/async.ts (4)
  • reject (123-127)
  • promise (128-130)
  • Deferred (86-95)
  • createDeferred (142-144)
🪛 ast-grep (0.40.0)
src/interactive-window/outputs/tracebackFormatter.ts

[warning] 157-157: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(\\[.*?;32m${escapeRegExp(displayPath)})
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🪛 dotenv-linter (4.0.0)
src/test/datascience/.env

[warning] 2-2: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🪛 GitHub Actions: CD
build/ci/postInstall.js

[error] 1-1: Cannot find module 'colors/safe' imported from build/ci/postInstall.js. Node attempted to resolve colors/safe; consider using 'colors/safe.js' or correcting the import path. Command that failed: npm run download-api && node ./build/ci/postInstall.js

package.json

[error] 1-1: npm run download-api && node ./build/ci/postInstall.js failed during postinstall with exit code 1.

🪛 GitHub Actions: CI
build/ci/postInstall.js

[error] 1-1: Cannot find module 'colors/safe' imported from build/ci/postInstall.js. Did you mean to import 'colors/safe.js'?

package.json

[error] 1-1: Command failed: npm run download-api && node ./build/ci/postInstall.js. Process exited with code 1.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review continued from previous batch...

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 41

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (9)
src/platform/errors/index.ts (1)

104-104: Use centralized logger.

Per coding guidelines, use the centralized logger instead of console.error.

Based on coding guidelines.

-        console.error('Error type is not defined', error);
+        logger.error('Error type is not defined', error);

Add import at the top:

 import * as stackTrace from 'stack-trace';
 import { getTelemetrySafeHashedString } from '../telemetry/helpers';
+import { logger } from '../logging';
src/kernels/kernelAutoReConnectMonitor.unit.test.ts (2)

119-133: Update test to match timing pattern of related tests.

The test at lines 119-133 lacks clock.nextAsync() calls after event fires and between signal emissions, while parallel tests (lines 103-118, 228-242, 274-292) include them. Add the calls for consistency:

     onDidStartKernel.fire(instance(kernel.kernel));
+    await clock.nextAsync();
 
     // Send the kernel into connecting state & then disconnected.
     await kernel.onWillRestart();
     kernel.kernelConnectionStatusSignal.emit('connecting');
+    await clock.nextAsync();
     kernel.kernelConnectionStatusSignal.emit('disconnected');
+    await clock.nextAsync();
     onDidRestartKernel.fire(instance(kernel.kernel));
 
-    await clock.runAllAsync();
-
     verify(mockedVSCodeNamespaces.window.withProgress(anything(), anything())).never();

244-271: Timing pattern inconsistency confirmed. Update both tests to match suite pattern.

The second suite shows mixed patterns: updated tests use clock.nextAsync() after events while these two still use clock.runAllAsync(). Since both fire onDidStartKernel and emit signals, they should follow the same timing pattern as the other updated tests in this suite.

Apply the proposed diffs to align with the rest of the test suite.

src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (1)

246-345: Skipped pandas-install tests are well documented but leave a gap

The two test.skip cases around prompting to install pandas are clearly annotated with the esmock vs vscode‑mocking limitation, which is good. Still, these cover important user‑visible flows; it’d be worth tracking a follow‑up to re‑enable them (e.g., by refactoring to avoid double module systems or adding a small facade around VSCode APIs that esmock can replace without fighting the mocha loader).

src/kernels/kernelDependencyService.node.ts (1)

113-163: CancellationTokenSource is shadowed, so cancel checks never see it

Inside installMissingDependencies, the inner const cancelTokenSource = new CancellationTokenSource(); shadows the outer let cancelTokenSource, so later checks and disposal use undefined and never see the installer’s cancellation state.

-        const key = getComparisonKey(kernelConnection.interpreter.uri);
-        let promise = this.installPromises.get(key);
-        let cancelTokenSource: CancellationTokenSource | undefined;
-        if (!promise) {
-            const cancelTokenSource = new CancellationTokenSource();
+        const key = getComparisonKey(kernelConnection.interpreter.uri);
+        let promise = this.installPromises.get(key);
+        let cancelTokenSource: CancellationTokenSource | undefined;
+        if (!promise) {
+            cancelTokenSource = new CancellationTokenSource();
             const disposable = token.onCancellationRequested(() => {
                 cancelTokenSource.cancel();
                 disposable.dispose();
@@ -147,9 +147,9 @@
             };
             promise = ui.disableUI
                 ? install()
                 : KernelProgressReporter.wrapAndReportProgress(
                       resource,
                       DataScience.installingMissingDependencies,
                       install
                   );
             promise
                 .finally(() => {
                     disposable.dispose();
-                    cancelTokenSource.dispose();
+                    cancelTokenSource?.dispose();
                 })
                 .catch(noop);
             this.installPromises.set(key, promise);

This lets the later if (cancelTokenSource?.token?.isCancellationRequested || token.isCancellationRequested) check work as intended and avoids disposing an uninitialized source.

src/platform/interpreter/installer/pipenv.node.ts (1)

62-73: Trim .project content before path checks

fileUtilsNodeUtils.readFile(dotProjectFile) is used directly as a path. Pipenv’s .project file content can include trailing newlines/whitespace, which would make pathExists(projectDir) fail even when the directory exists.

Consider trimming the value:

-    const projectDir = await fileUtilsNodeUtils.readFile(dotProjectFile);
+    const projectDir = (await fileUtilsNodeUtils.readFile(dotProjectFile)).trim();

This keeps behavior the same for valid paths while handling common .project formatting.

src/interactive-window/editor-integration/codewatcher.unit.test.ts (1)

39-53: Helper-based editor setup is a solid improvement

Using initializeMockTextEditor to wire codeWatcher.setDocument, window.activeTextEditor, and selections makes these tests less brittle and closer to real VS Code behavior; the new usages in the run‑cell/advance tests look consistent.

Also applies to: 402-425, 582-606, 905-941, 945-991

src/kernels/execution/notebookUpdater.ts (1)

24-69: Export alias currently snapshots implementation; consider wrapper to honor stubs

Right now:

export const chainWithPendingUpdates = notebookUpdaterUtils.chainWithPendingUpdates;
export const clearPendingChainedUpdatesForTests = notebookUpdaterUtils.clearPendingChainedUpdatesForTests;

captures the current function values. If tests later stub notebookUpdaterUtils.chainWithPendingUpdates, callers that imported chainWithPendingUpdates directly will still invoke the original implementation.

If you want stubbing notebookUpdaterUtils to affect legacy imports as well, prefer forwarding wrappers:

export async function chainWithPendingUpdates(document: NotebookDocument, update: (edit: WorkspaceEdit) => void | Promise<void>) {
    return notebookUpdaterUtils.chainWithPendingUpdates(document, update);
}

export function clearPendingChainedUpdatesForTests() {
    return notebookUpdaterUtils.clearPendingChainedUpdatesForTests();
}

This keeps the public API identical while making the mutable utils object the single dispatch point.

build/esbuild/build.ts (1)

36-69: Externals separation fixes aliasing; consider simplifying extension.node externals

Splitting webExternals / desktopExternals into independent arrays avoids the earlier shared-state mutation issue—nice improvement.

For the desktop extension entry you currently do:

const external = [...(target === 'web' ? webExternals : commonExternals)];
if (source.toLowerCase().endsWith('extension.node.ts')) {
    external.push(...desktopExternals);
}

Since desktopExternals already includes commonExternals, this doubles those entries for extension.node.ts. Esbuild tolerates duplicates, but you could make intent clearer and avoid redundancy with something like:

const external =
    target === 'web'
        ? [...webExternals]
        : source.toLowerCase().endsWith('extension.node.ts')
        ? [...desktopExternals]
        : [...commonExternals];

Functionally equivalent, but a bit easier to reason about.

Also applies to: 228-231

♻️ Duplicate comments (20)
src/interactive-window/shiftEnterBanner.unit.test.ts (1)

99-99: setTimeout still unreliable for async coordination.

As previously noted, setTimeout(resolve, 0) doesn't guarantee async work completes. Await the actual promise chain or use a proper test helper.

src/extension.node.proxy.ts (1)

22-28: Production fallback still broken.

Past review identified this: in production, both entryPoint and fallbackPath are './extension.node.js'. If the initial import fails, line 22 won't match (error is about './extension.node.js', not '../out/extension.node.js'), so it logs then retries the same path.

Fix: only fall back in test mode, or rethrow in production.

     } catch (ex) {
-        if (!ex.toString().includes(`Cannot find module '../out/extension.node.js'`)) {
-            console.error('Failed to activate extension, falling back to `./extension.node.js`', ex);
-        }
-        // In smoke tests, we do not want to load the out/extension.node.
-        const fallbackPath = './extension.node.js';
-        realEntryPoint = await import(/* webpackIgnore: true */ fallbackPath);
-        return realEntryPoint.activate(context);
+        if (context.extensionMode === ExtensionMode.Test &&
+            ex.toString().includes(`Cannot find module '../out/extension.node.js'`)) {
+            // In smoke tests, we do not want to load the out/extension.node.
+            const fallbackPath = './extension.node.js';
+            realEntryPoint = await import(/* webpackIgnore: true */ fallbackPath);
+            return realEntryPoint.activate(context);
+        }
+        throw ex;
     }
src/standalone/intellisense/resolveCompletionItem.unit.test.ts (1)

134-140: Document the cancellation stub.

Please add a brief note that this stub intentionally ignores cancellation so future callers don't expect a CancellationError here.

build/esbuild/jquery.js (1)

4-5: ESM import syntax is correct, but jQuery 1.11.2 has known CVEs.

The migration to import is proper, but as noted in the previous review, jQuery 1.11.2 contains multiple security vulnerabilities (XSS, Prototype Pollution). Given this PR's security focus (upgrading vega-lite), consider upgrading jQuery to >= 3.5.0.

src/kernels/jupyter/session/jupyterLabHelper.ts (1)

37-38: Comment incorrectly claims "lazy load"—module is eagerly imported.

The top-level import * as jupyterLabServices loads the module when this file is evaluated. The getter only caches an already-imported namespace. Update the comment to reflect caching behavior, not lazy loading.

src/platform/common/platform/fs-paths.ts (1)

12-28: getHomeDir returns undefined—breaks Node.js callers.

As flagged in the previous review, multiple Node.js files import getDisplayPath from fs-paths (not fs-paths.node) and rely on the automatic home directory fallback at line 50. Since getHomeDir() now returns undefined, these calls will fail to resolve home-relative paths in Node.js contexts.

Affected files include pythonEnvironmentPicker.node.ts and globalPythonExePathService.node.ts. Either migrate those imports to fs-paths.node or pass homePath explicitly.

build/remove-js-extensions.mjs (1)

35-57: Regex fails to match ../ relative imports.

The pattern (\.\/?[^'"]+) on lines 44 and 46 only matches ./foo.js but not ../foo.js or ../../foo.js. The comment on line 40 claims it handles ../bar/index.js, but it doesn't.

Apply this diff to fix both patterns:

     const patterns = [
         // import ... from './path.js' or '../path.js'
-        /(\bfrom\s+['"])(\.\/?[^'"]+)\.js(['"])/g,
+        /(\bfrom\s+['"])(\.{1,2}\/[^'"]+)\.js(['"])/g,
         // import('./path.js') or import('../path.js')
-        /(\bimport\s*\(\s*['"])(\.\/?[^'"]+)\.js(['"])/g,
+        /(\bimport\s*\(\s*['"])(\.{1,2}\/[^'"]+)\.js(['"])/g,
     ];
src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (1)

69-244: Repeated esmock + executeSilently stubbing could be DRYed up

Each pandas‑version test repeats the same pattern: create a mockExecuteSilently stub, esmock kernelDataViewerDependencyImplementation with that stub, then esmock DataViewerDependencyService with the implementation, and finally assert on mockExecuteSilently.getCalls().map(call => call.lastArg). Behavior is correct and clear, but a small helper (e.g. createDependencyServiceWithExecuteSilentlyStub(...)) would remove boilerplate and reduce drift risk if paths change.

src/test/web/customReporter.ts (1)

208-221: require for Mocha internals may break under pure ESM loaders

The lazy require('mocha/lib/utils') and require('mocha/lib/reporters/spec') inside an otherwise ESM module will fail if require is not injected by the runtime (pure ESM Node + loader won’t define it by default). Consider swapping to dynamic imports or createRequire(import.meta.url) for these internals, or at least confirm your mocha ES loader guarantees require here.

You can sanity‑check remaining require usage in this module with:

#!/bin/bash
rg -n "require\\('mocha" src/test/web/customReporter.* -n
```<!-- review_comment_end -->

</blockquote></details>
<details>
<summary>src/platform/interpreter/installer/poetryInstaller.unit.test.ts (1)</summary><blockquote>

`22-37`: **Keep `poetryInstaller` typed to the concrete test class instead of `any`**

The new esmock wiring doesn’t change it, but `let poetryInstaller: any;` still throws away type safety for the installer. Typing this as your local `TestInstaller` (or `PoetryInstaller`) would let these tests compile against the real API and catch accidental signature changes.

<!-- review_comment_end -->

</blockquote></details>
<details>
<summary>src/notebooks/controllers/vscodeNotebookController.unit.test.ts (2)</summary><blockquote>

`626-657`: **Deduplicate NotebookController mock construction with a small factory**

Both `thenCall` stubs build nearly identical controller-shaped objects (one just adds `variableProvider`). This was already pointed out; duplicating the shape makes future API changes easy to miss.




Consider extracting a helper like:

```ts
function createMockNotebookController(
    id: string,
    view: string,
    label: string,
    handler: any,
    rendererScripts: any,
    extra?: Partial<NotebookController>
): NotebookController {
    const base: any = {
        id,
        label,
        description: '',
        detail: '',
        supportedLanguages: [],
        supportsExecutionOrder: false,
        interruptHandler: undefined,
        executeHandler: handler,
        onDidChangeSelectedNotebooks: onDidChangeSelectedNotebooks.event,
        onDidReceiveMessage: new EventEmitter<any>().event,
        dispose: () => {},
        asWebviewUri: (uri: Uri) => uri,
        postMessage: () => Promise.resolve(true),
        updateNotebookAffinity: () => {},
        createNotebookCellExecution: () => ({}) as any,
        createNotebookExecution: () => ({}) as any,
        notebookType: view,
        rendererScripts: rendererScripts || []
    };
    return { ...base, ...extra } as NotebookController;
}

and have both thenCall sites call createMockNotebookController(...), passing { variableProvider: undefined } only in the “API available” test.

Also applies to: 662-695


106-141: Remove debug console.log noise from controller mock

The console.log calls inside the createNotebookController override spam unit-test output and don’t add assertion value; this was already flagged in an earlier review.

-        (mockedVSCode as any).notebooks.createNotebookController = (
+        (mockedVSCode as any).notebooks.createNotebookController = (
             _id: string,
             _view: string,
             _label: string,
             _handler: any,
             _rendererScripts: any
         ) => {
-            console.log('MOCK createNotebookController CALLED with id:', _id);
             const mockControllerObject: any = {
                 id: _id,
                 label: _label,
@@ -132,12 +131,7 @@
                 notebookType: _view,
                 rendererScripts: _rendererScripts || []
             };
-            console.log('MOCK createNotebookController RETURNING controller with id:', mockControllerObject.id);
             return mockControllerObject;
         };
-        console.log(
-            'mockedVSCode.notebooks.createNotebookController:',
-            typeof (mockedVSCode as any).notebooks.createNotebookController
-        );
src/interactive-window/editor-integration/codewatcher.ts (1)

320-334: Remove raw console.log debugging from runCell

These debug prints will spam the extension host logs and bypass the existing logging/telemetry path (you already have debugDecorator here). Suggest removing them before merge or routing through the structured logging utilities instead.

src/notebooks/deepnote/deepnoteExplorerView.unit.test.ts (1)

27-39: Fallback UUID may hide test bugs.

When the mock exhausts the provided uuids array, it returns fallback-uuid-${callCount++} instead of failing. This could mask tests generating more UUIDs than expected.

Consider throwing an error when exhausted:

 function createUuidMock(uuids: string[]): sinon.SinonStub {
     let callCount = 0;
     const stub = sinon.stub(uuidModule.uuidUtils, 'generateUuid');
     stub.callsFake(() => {
         if (callCount < uuids.length) {
             return uuids[callCount++];
         }
-        // Fallback to a default UUID if we run out of mocked values
-        return `fallback-uuid-${callCount++}`;
+        throw new Error(`Unexpected generateUuid call #${callCount}`);
     });
     return stub;
 }
src/kernels/deepnote/environments/deepnoteEnvironmentTreeItem.node.ts (1)

28-93: Constructor is still doing a lot; consider extracting pure helpers

The inlined environment/tooltip/relative‑time logic is functionally fine, but the constructor now owns several distinct concerns (item wiring, relative time formatting, tooltip building). You can keep things ESM‑safe and avoid this binding issues by moving this logic into standalone pure functions like computeLastUsedLabel(lastUsedAt: Date) and buildEnvironmentTooltip(environment: DeepnoteEnvironment) defined outside the class, then calling them from the constructor. That keeps the constructor lean and makes the formatting behavior easier to test.

src/notebooks/deepnote/openInDeepnoteHandler.node.unit.test.ts (1)

55-68: Teardown stub resets are still redundant

The stubs (initImportStub, uploadFileStub, getDeepnoteDomainStub) are freshly created and configured in each setup, so resetting and reconfiguring them in teardown doesn’t affect subsequent tests and just adds noise. Keeping only sandbox.restore() here is sufficient.

src/platform/telemetry/index.ts (1)

26-33: Align isTelemetrySupported comment with new reporter‑based check and confirm usage context

The comment still talks about vscode being “imported at the top”, but isTelemetrySupported now just tries to construct a singleton TelemetryReporter via getTelemetryReporter() inside a try/catch. The behavior is fine, but the comment should say that support is determined by successfully creating a TelemetryReporter from @vscode/extension-telemetry, and that failures are treated as “telemetry not supported”.

Also, please reconfirm that constructing TelemetryReporter(AppinsightsKey) is valid in all contexts where this module is loaded (including any debug‑adapter or non‑extension hosts), and that failing to resolve the module or key won’t produce undesirable side‑effects beyond returning false.

Also applies to: 80-86

src/notebooks/deepnote/deepnoteDataConverter.ts (1)

15-16: Use the vega-lite/types_unstable entry point instead of deep file paths

These type-only imports currently deep-import from vega-lite/types_unstable/channeldef.js and .../spec/index.js, which is more fragile than the documented vega-lite/types_unstable entry point and may break when vega‑lite reshuffles internal files.

You can keep the same types while relying on the supported export by collapsing this to something like:

import type { Field, LayerSpec, TopLevel } from 'vega-lite/types_unstable';

This avoids depending on internal file layout while still acknowledging the “unstable types” contract.

build/mocha-esm-loader.js (1)

90-292: Consider extracting the vscode mock module template for maintainability

The huge inline template string that builds the mocked vscode module is hard to maintain; extracting it into a small helper/module (e.g., generateVSCodeMockSource(vscodeMockPath)) would keep this loader focused on wiring while leaving the mock shape in a dedicated file.

src/platform/interpreter/installer/poetry.unit.test.ts (1)

122-155: Tighten Poetry typing and mirror full fileUtils surface in this suite as well

Two follow‑ups remain here:

  1. let Poetry: any; loses type safety for this suite. Typing it as the real class (e.g. typeof import('../../../platform/interpreter/installer/poetry.node').Poetry) would let the compiler catch API drifts.
  2. The fileUtils.node mock in this block omits the async pathExists used by Poetry.getEnvListCached, so future changes that cause that path to execute could hit the real filesystem. Mirroring the earlier suite and adding pathExists: () => Promise.resolve(true) would keep these tests fully isolated.

Teardown also uses esmock.purge(Poetry), which has the same “named export vs. module value” concern as the isPoetryEnvironment suite—worth aligning with whatever pattern you adopt there.

For the current esmock version in this repo, should purge() be called with the module exports object returned by esmock(...) (or the value from esmock.p(...)) rather than a single named export like module.Poetry, to reliably clear that module's mock cache?

Also applies to: 169-255

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review continued from previous batch...

The CI build was failing due to peer dependency conflicts between
react-vega@7.7.1 (which depends on vega-embed@6.5.1) and vega@6.2.0.

vega-embed@6.5.1 requires vega@^5.8.0 as a peer dependency, but we're
using vega@6.2.0. This causes `vsce package` to fail when it runs
`npm list --production` to validate dependencies.

The --no-dependencies flag tells vsce to skip the npm list validation
check. This is safe because:
1. The peer dependency mismatch doesn't affect runtime functionality
2. We have vega-embed@^7.1.0 as a direct dependency which supports vega@6
3. The extension builds and runs correctly despite the warnings

Fixes the "Build & Package Extension" workflow failure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
src/platform/errors/index.ts (2)

100-106: Use centralized logger instead of console.error

Per platform guidelines, this should go through the shared logger, not console.error. Consider importing the logger (with the appropriate relative path from src/platform/errors/index.ts) and replacing this call to keep logging consistent.


10-25: Fix broken fetch error detection logic and centralized logging violation

The local FetchError definition at line 10 breaks the entire fetch error detection chain:

  • !FetchError is always false (class exists locally), so isBrowserFetchError never triggers
  • isFetchError reduces to checking error instanceof FetchError, which always fails since no error is ever thrown as this local class
  • Result: fetch errors never categorized as 'fetcherror'—telemetry regression

Also, line 104 uses console.error instead of the centralized logger per platform guidelines.

Actions:

  1. Either restore FetchError as an ambient/external constructor or detect fetch errors via error.name/error.message patterns only
  2. Replace console.error with import { logger } from '../platform/logging' and use logger.error(...)
  3. Verify telemetry flows with fetch-related tests
src/webviews/extension-side/dataviewer/dataViewerDependencyServiceKernel.node.unit.test.ts (1)

246-345: Add GitHub issue reference to track skipped test debt

The codebase convention (seen across multiple test files) is to reference GitHub issues for blocked/skipped tests. These two tests lack such a reference despite having unresolved dependencies (esmock/VSCode mocking conflict). Add a GitHub issue link in the skip comment to track this technical debt, or implement the suggested adapter approach to unblock the tests.

src/interactive-window/editor-integration/codewatcher.unit.test.ts (1)

39-53: Good refactor: centralized mock editor initialization

The initializeMockTextEditor helper eliminates duplication and makes test setup explicit and consistent.

src/test/analysisEngineTest.node.ts (1)

18-18: Mixed module systems detected.

Line 18 uses require() (CommonJS) while the file has been migrated to ESM. This inconsistency may cause runtime issues.

Consider converting to dynamic import:

-    require('../../node_modules/vscode/bin/test');
+    await import('../../node_modules/vscode/bin/test');

Or if the module doesn't export anything useful and is side-effect only:

 function start() {
     console.log('*'.repeat(100));
     console.log('Start language server tests');
-    require('../../node_modules/vscode/bin/test');
+    await import('../../node_modules/vscode/bin/test');
 }
-start();
+void start();
build/eslint-rules/index.js (1)

64-146: Add .test.ts exemption to dont-use-process rule

The rule lacks the .test.ts guard that both dont-use-fspath and dont-use-filename include. Sync the three rules by adding !fileName.endsWith('.test.ts') to the condition, or document why dont-use-process intentionally differs.

if (
    !fileName.endsWith('.node.ts') &&
    !fileName.endsWith('.test.ts') &&  // Add this line
    objectName === 'process' &&
    !node.computed &&
    propertyName &&
    propertyName === 'env'
) {
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (2)

284-300: Session construction path matches mocking, but initial mock is redundant.

You create session = mock<RawSessionConnectionType>(); and then immediately overwrite it with a real RawSessionConnection. That first mock is unused and can be removed to reduce noise.


341-361: Startup cancellation tests likely no longer control the real kernel.

These tests stub kernel.requestKernelInfo() on the ts‑mock kernel, but RawSessionConnection now talks to kernelObj returned from the patched KernelConnection. As a result, the fake timers and injected delay/pending promise may not affect the SUT, and the assertions about timeouts/cancellation might not be exercising the intended path. Consider stubbing kernelObj.requestKernelInfo instead, or exposing the actual kernel used by the session for stubbing.

build/webpack/common.js (1)

56-104: ZeroMQ prebuild selection logic unchanged; minor typo in error message.

Platform detection and returned folder lists match the prior logic. The only nit is the final error: Unknown platform '${vsceTarget}'} has an extra } in the string; consider trimming it for clarity.

src/test/web/customReporter.ts (1)

93-107: Access fs-extra exports via .default when using dynamic import.

When dynamically importing CommonJS modules, Node exposes CommonJS exports as the module's default export. Change lines 104–106 to:

fs.default.ensureDirSync(logDir.fsPath);
// eslint-disable-next-line local-rules/dont-use-fspath
fs.default.writeFileSync(logFile.fsPath, JSON.stringify(messages));

Or use the ESM entry: const fs = await import('fs-extra/esm'); (no .default needed).

♻️ Duplicate comments (28)
src/kernels/deepnote/environments/deepnoteEnvironmentTreeItem.node.ts (1)

28-77: Functionally correct; past refactoring suggestion still applies.

The inlined logic for relative time and tooltip building works correctly. The past review comment about extracting pure helpers remains valid if you want to improve testability while staying ESM-safe.

src/interactive-window/shiftEnterBanner.unit.test.ts (1)

99-99: Still using unreliable zero-timeout wait.

Past comment flagged this same line. Await actual async completion from showBanner() instead.

src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (1)

220-246: Resolve Biome noThenProperty warning while keeping the non-thenable mock

The then: undefined on mockNotebookDoc is exactly what we want here to avoid the mock being treated as a thenable in async flows, in line with the unit-test guideline. Biome’s noThenProperty rule will still flag this, though.

Recommend a narrow suppression to keep both behaviors:

-            const mockNotebookDoc = {
-                then: undefined, // Prevent mock from being treated as a Promise-like thenable
+            // biome-ignore lint/suspicious/noThenProperty: test mock should not be thenable
+            const mockNotebookDoc = {
+                then: undefined, // Prevent mock from being treated as a Promise-like thenable

This keeps the mock safe in promise-returning contexts without fighting the linter.

src/standalone/intellisense/resolveCompletionItem.unit.test.ts (1)

85-165: Document that the cancellation stub intentionally ignores cancellation

The esmock wiring and raceTimeoutError stub integrate well with fake timers and exercise timeout semantics without depending on the real async helpers. The raceCancellation stub, however, always returns the original promise and never produces a CancellationError, so any future change to production cancellation behavior could be misleading when reading these tests.

Adding a brief inline comment here would make this intent explicit:

-            '../../platform/common/cancellation': {
-                raceCancellation: (_token: CancellationToken, promise: Promise<any>) => promise,
+            '../../platform/common/cancellation': {
+                // NOTE: This stub intentionally ignores cancellation. If production
+                // raceCancellation starts rejecting with a CancellationError, these
+                // tests should be updated to cover that path.
+                raceCancellation: (_token: CancellationToken, promise: Promise<any>) => promise,
                 wrapCancellationTokens: (token: CancellationToken) => ({
                     token,
                     cancel: () => {},
                     dispose: () => {}
                 })
             },
src/webviews/extension-side/dataviewer/dataViewerDependencyService.unit.test.ts (2)

201-286: Skipped install-flow tests still lack tracking or workaround

The two “Prompt to install pandas…” tests remain skipped for esmock/VSCode mocking reasons, so the key “prompt → install” and “prompt → user declines” flows stay untested. As previously noted, please either reference a tracking issue in these comments or introduce a small adapter layer around VSCode + executeSilently that can be mocked without esmock/loader conflicts, then re-enable the tests.


52-76: Tighten executeSilently stubs and consider DRY-ing shared wiring

These pandas-version tests all use sinon.stub().returns(Promise.resolve([...])) plus identical esmock wiring for ./kernelDataViewerDependencyImplementation and ./dataViewerDependencyService. You can make the stubs a bit clearer with sinon.stub().resolves([...]) and/or extract a helper that performs the common esmock + service construction so each test only defines the version payload and assertions. This mirrors earlier feedback on the same patterns.

Also applies to: 88-112, 124-148, 164-188

src/kernels/jupyter/session/jupyterLabHelper.ts (1)

37-38: Update "lazy load" comment—namespace is eagerly imported.

The top-level import * as jupyterLabServices executes at module load time; the getter merely caches the pre-loaded namespace. Either update the comment to reflect caching or switch to dynamic import() if true laziness matters.

build/esbuild/jquery.js (2)

4-4: Fix typo in comment.

"requried" → "required"


5-5: jQuery 1.11.2 has known security vulnerabilities.

Given this PR's security focus (upgrading vega-lite and js-yaml), the ancient jQuery 1.11.2 should be upgraded to >= 3.4.0 to patch MODERATE CVEs including XSS and Prototype Pollution.

src/interactive-window/editor-integration/codewatcher.ts (1)

322-332: Use centralized logger instead of console.log.

These debug statements bypass the existing logging pipeline (you already have debugDecorator on this method and logger imported). Replace with logger.trace() or remove before merge.

As per coding guidelines

build/remove-js-extensions.mjs (1)

35-57: Regex still doesn't match ../ relative imports.

The pattern \.\/?[^'"]+ only handles ./foo.js, not ../foo.js or deeper paths. Parent-directory imports with .js extensions won't be processed.

Apply this fix to handle both . and .. prefixes:

     const patterns = [
         // import ... from './path.js' or '../path.js'
-        /(\bfrom\s+['"])(\.\/?[^'"]+)\.js(['"])/g,
+        /(\bfrom\s+['"])(\.{1,2}\/[^'"]+)\.js(['"])/g,
         // import('./path.js') or import('../path.js')
-        /(\bimport\s*\(\s*['"])(\.\/?[^'"]+)\.js(['"])/g,
+        /(\bimport\s*\(\s*['"])(\.{1,2}\/[^'"]+)\.js(['"])/g,
     ];
build/fix-directory-imports.mjs (1)

48-59: Patterns match any quoted string, not just import statements.

The regexes will rewrite matching paths in any context (comments, strings, etc.), not just module specifiers. If this broad scope is unintended, restrict matches to import/export/require contexts. Otherwise, the implementation is functional.

src/notebooks/deepnote/openInDeepnoteHandler.node.unit.test.ts (1)

55-68: Teardown stub resets are redundant.

Since setup recreates these stubs fresh for each test, the .reset() and reconfiguration calls in teardown have no effect. You can remove lines 58-67 and rely solely on setup initialization.

src/notebooks/deepnote/deepnoteDataConverter.ts (1)

15-16: Refactor to use the entry point per past review.

Deep imports from internal vega-lite files remain fragile. Use the public types_unstable entry point:

-import type { Field } from 'vega-lite/types_unstable/channeldef.js';
-import type { LayerSpec, TopLevel } from 'vega-lite/types_unstable/spec/index.js';
+import type { Field, LayerSpec, TopLevel } from 'vega-lite/types_unstable';
src/notebooks/deepnote/deepnoteTreeDataProvider.unit.test.ts (1)

403-412: Test fallback duplicates production logic.

Manual field updates replicate updateVisualFields behavior. If production changes, this fallback becomes stale.

Consider adding a comment referencing the production implementation.

src/platform/telemetry/index.ts (1)

28-29: Outdated comment - already flagged in previous review.

The comment mentions "vscode … imported at the top" but the support check actually verifies getTelemetryReporter(). As noted in the previous review, the comment should reflect that telemetry support is determined by successfully creating a TelemetryReporter instance.

build/preDebugWebTest.js (1)

23-27: LGTM – temp directory creation added.

The past review concern is resolved; fs.ensureDir(tempDir) ensures the directory exists before writing the PID file.

src/platform/constants.node.ts (1)

20-28: Property name corrected.

Past review flagged isPreRelesVersionOfJupyterExtension typo; now correctly reads isPreRelease from the package. Fallback to true for dev builds is appropriate.

src/notebooks/deepnote/deepnoteExplorerView.unit.test.ts (1)

27-39: Fallback UUID masks unexpected calls.

When callCount >= uuids.length, returning a fallback string hides tests that generate more UUIDs than anticipated. Throwing an error would catch these bugs earlier.

Consider:

     stub.callsFake(() => {
         if (callCount < uuids.length) {
             return uuids[callCount++];
         }
-        // Fallback to a default UUID if we run out of mocked values
-        return `fallback-uuid-${callCount++}`;
+        throw new Error(`Unexpected generateUuid call #${callCount + 1} (only ${uuids.length} provided)`);
     });
src/platform/common/platform/fs-paths.ts (1)

12-28: getHomeDir breaks Node.js callers—still unresolved.

Returning undefined in all contexts breaks Node.js files that import getDisplayPath from fs-paths (not fs-paths.node). Past review identified pythonEnvironmentPicker.node.ts and globalPythonExePathService.node.ts as affected.

Verify all .node.ts files either:

  1. Import from fs-paths.node (which wraps with explicit homePath), or
  2. Pass homePathUri explicitly to getDisplayPath()
#!/bin/bash
# Find Node.js files importing getDisplayPath from fs-paths (not fs-paths.node)
rg -n "import.*getDisplayPath.*from.*['\"].*fs-paths['\"]" --type=ts -g "*.node.ts" | grep -v "fs-paths\.node"

# Check their getDisplayPath calls for missing homePathUri argument
rg -n "getDisplayPath\(" --type=ts -g "*.node.ts" -B2 -A2
src/extension.node.proxy.ts (1)

16-28: Redundant fallback in production mode.

In production, both entryPoint and fallbackPath are './extension.node.js'. The error check (line 22) only matches the test path, so production failures log then retry the same path—redundant and confusing.

Consider restructuring to avoid retrying identical paths:

-    const entryPoint =
-        context.extensionMode === ExtensionMode.Test ? '../out/extension.node.js' : './extension.node.js';
+    const isTestMode = context.extensionMode === ExtensionMode.Test;
+    const entryPoint = isTestMode ? '../out/extension.node.js' : './extension.node.js';
     try {
         realEntryPoint = await import(/* webpackIgnore: true */ entryPoint);
         return realEntryPoint.activate(context);
     } catch (ex) {
-        if (!ex.toString().includes(`Cannot find module '../out/extension.node.js'`)) {
+        if (!isTestMode || !ex.toString().includes(`Cannot find module '../out/extension.node.js'`)) {
-            console.error('Failed to activate extension, falling back to `./extension.node.js`', ex);
+            throw ex;
         }
         // In smoke tests, we do not want to load the out/extension.node.
         const fallbackPath = './extension.node.js';
         realEntryPoint = await import(/* webpackIgnore: true */ fallbackPath);
         return realEntryPoint.activate(context);
     }
src/platform/interpreter/installer/poetry.unit.test.ts (1)

18-52: Tighten Poetry typing, stub async pathExists in all suites, and purge the right esmock handle

A few test‑hygiene points here:

  • Poetry is still declared as any (Line 123). Typing it as typeof import('../../../platform/interpreter/installer/poetry.node').Poetry (or importing that type) will keep the tests aligned with the real class surface.
  • In the second suite’s esmock config for fileUtils.node (Lines 137–144), pathExistsSync is stubbed but async pathExists is not, so Poetry.getEnvListCached can still touch the real filesystem. Mirroring the first suite and adding pathExists: () => Promise.resolve(true) here would keep these tests hermetic.
  • esmock.purge is invoked with isPoetryEnvironment / Poetry (exported symbols) rather than the esmocked module object. It’s safer to keep the module reference from await esmock(...) (e.g. let poetryModule) and call esmock.purge(poetryModule) in teardown to ensure mocks are fully cleaned up.
What is the recommended way to use `esmock.purge` to clean up mocked ES modules between tests? Does it expect the module object returned from `esmock(...)`, the module path, or can it safely accept individual exported symbols?

Also applies to: 54-57, 123-155, 137-148, 215-248

src/platform/interpreter/installer/poetryInstaller.unit.test.ts (1)

22-37: Strengthen test typing and mocks: poetryInstaller type, getUserHomeDir value, and esmock cleanup

A couple of improvements here:

  • poetryInstaller is declared as any (Line 27). You can type it as TestInstaller (or PoetryInstaller if you prefer not to keep the subclass) so the tests stay aligned with the real installer API.
  • The getUserHomeDir mock returns undefined (Line 84). If production code ever calls getUserHomeDir().fsPath, this test will fail with a TypeError. Returning a dummy Uri, e.g. Uri.file('/users/test'), keeps the home directory fake without risking crashes.
  • Setup uses esmock to create module instances, but teardown only calls sinon.restore() and leaves esmock.purge commented out. It’s safer to retain the modules returned from esmock(...) (e.g. let poetryModule, poetryInstallerModule;) and call esmock.purge(poetryModule); esmock.purge(poetryInstallerModule); in teardown to avoid mock leakage into other tests.
For `esmock`, when mocking a module that itself imports other mocked modules, what is the recommended pattern for purging those mocks between tests? Is it sufficient to call `esmock.purge` with each top-level mocked module returned from `esmock(...)`?

Also applies to: 38-57, 73-96, 97-111, 123-130

src/notebooks/controllers/vscodeNotebookController.unit.test.ts (2)

627-657: Deduplicate controller mock construction in thenCall stubs

Both thenCall handlers build nearly identical NotebookController objects (one just adds variableProvider), which is brittle if the shape evolves; a small shared factory helper would keep them in sync.

If you extract a helper, re-run the VSCodeNotebookController.create tests to confirm both variable‑provider branches still behave as expected.

Also applies to: 672-695


106-141: Remove debug logging from createNotebookController override

The custom createNotebookController override is well‑shaped, but the console.log calls don’t feed any assertions and will clutter test output; they can be safely removed.

After dropping the logs, rerun this suite to confirm there are no hidden timing or ordering dependencies on stdout.

build/mocha-esm-loader.js (1)

90-292: Consider extracting the vscode mock template for readability

The large inline template for the vscode mock makes this loader hard to scan; extracting it into a helper (e.g., generateVSCodeMockSource(vscodeMockPath)) would improve maintainability without changing behavior. This mirrors the earlier suggestion on this file.

If you apply this refactor, rerun the unit tests that rely on the mocked vscode module to ensure nothing regresses.

src/test/web/customReporter.ts (1)

208-221: Lazy-loading Mocha internals with require in ESM is still fragile.

This module is now ESM, but the constructor still assumes a CJS require is present for mocha/lib/utils and mocha/lib/reporters/spec. In a pure ESM/node-loader path this will throw unless the test harness shims require. Consider switching to createRequire(import.meta.url) or await import(...) for these, or at least document/guard the assumption.

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (1)

200-257: Kernel mock object missing then: undefined and may confuse tests.

The new plain kernelObj is a good improvement over deep ts‑mockito graphs, but it still lacks a then: undefined property as per the test guidelines; add it to avoid it ever being treated as a thenable when coming out of a promise.
Also, note that jupyterLabKernel.KernelConnection now returns kernelObj, while the kernel ts‑mock created in this function is unused except in test stubs below. Any when(kernel.…) stubbing will not affect kernelObj, so related tests may no longer be configuring the actual kernel used by RawSessionConnection.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (1)

342-362: Cancellation tests likely broken due to ineffective stubbing.

Lines 346 and 333 stub kernel.requestKernelInfo(), but per the issue at lines 199-260, this won't affect kernelObj.requestKernelInfo. Either skip these tests alongside lines 323-329, or fix the kernel mocking approach first.

build/postDebugWebTest.js (1)

12-18: Change jupyter.pid to deepnote.pid to match preDebugWebTest

The search confirms the mismatch: preDebugWebTest.js writes deepnote.pid (line 27), while postDebugWebTest.js reads jupyter.pid (line 12). This prevents the cleanup script from finding and killing the Jupyter process.

-    const file = path.join(__dirname, '..', 'temp', 'jupyter.pid');
+    const file = path.join(__dirname, '..', 'temp', 'deepnote.pid');
♻️ Duplicate comments (7)
package.json (1)

2511-2511: Dependency updates align with PR objectives

js-yaml patch and Vega v6 suite address stated vulnerabilities. esmock addition enables ESM test mocking. Note: the MIME type at line 2212 still references v5 and should be updated to v6, as flagged in the previous review.

Also applies to: 2545-2547, 2650-2650

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (3)

199-260: ts-mockito mock created but never used; test stubs are ineffective.

Line 250 creates a kernel mock that's returned (line 259), but tests stub behavior via when(kernel....) while kernelObj (not kernel) is what KernelConnection returns. Any stubbing like when(kernel.requestKernelInfo()).thenCall(...) at lines 333, 346 won't execute—those tests will use kernelObj.requestKernelInfo instead, breaking timeout/cancellation scenarios.

Either remove the ts-mockito mock entirely and adjust tests to manipulate kernelObj directly, or revert to the ts-mockito-based approach from the previous review comment (lines 200-258) where when(kernel....) stubs drive the instance.

Note: Line 208's then: undefined is correct per coding guidelines; the static analysis error is a false positive.


318-323: TODO clearly documents the mocking gap.

The explanation is accurate. However, ensure lines 342-362 (cancellation tests) are intentionally left enabled—they may fail if they rely on stubbing kernel.requestKernelInfo().


364-366: Skipped suite is reasonable; ensure follow-up is tracked.

Clear rationale for skipping. Just verify there's an issue tracking the ZeroMQ mocking completion so these tests can be re-enabled.

build/fix-telemetry-imports.mjs (1)

4-13: Drop redundant dirname import.

You already import path; you can use path.dirname(__filename) and remove the separate { dirname } import to keep imports consistent with the other build scripts.

-import path from 'path';
-import { fileURLToPath } from 'url';
-import { dirname } from 'path';
+import path from 'path';
+import { fileURLToPath } from 'url';

 const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
+const __dirname = path.dirname(__filename);
build/fix-directory-imports.mjs (2)

4-13: Unify path usage; remove extra dirname import.

Same as other build scripts, you can rely on path.dirname instead of importing dirname separately.

-import path from 'path';
-import { fileURLToPath } from 'url';
-import { dirname } from 'path';
+import path from 'path';
+import { fileURLToPath } from 'url';

 const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
+const __dirname = path.dirname(__filename);

42-58: Regex can mis-handle deeper prefixes like '../../platform/logging.js'.

The current pattern uses (?:.*\\/) inside the captured prefix, which can interact poorly with ${dirImport} and fail to match multi-level paths (e.g., '../../platform/logging.js' for platform/logging). The earlier suggested form with constrained segments is safer.

Consider reverting to a variant that preserves any relative prefix while matching the directory import cleanly:

-        const pattern = new RegExp(`(['"])((?:\\.\\.\\/|\\.\\/)(?:.*\\/)?)${dirImport}\\.js(['"])`, 'g');
-
-        const newModified = modified.replace(pattern, (match, quote1, prefix, quote2) => {
-            changeCount++;
-            return `${quote1}${prefix}${dirImport}/index.js${quote2}`;
-        });
-        modified = newModified;
+        const pattern = new RegExp(
+            `(['"])(\\.\\.?\\/(?:[^'"]+\\/)*?)${dirImport}\\.js(['"])`,
+            'g',
+        );
+
+        modified = modified.replace(pattern, (_match, quote1, prefix, quote2) => {
+            changeCount++;
+            return `${quote1}${prefix}${dirImport}/index.js${quote2}`;
+        });

This keeps any ./, ../, or ../../foo/ prefix intact and reliably rewrites only the targeted directory import.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9c4d971 and 5908dd0.

📒 Files selected for processing (15)
  • build/add-js-extensions.mjs (1 hunks)
  • build/constants.js (1 hunks)
  • build/fix-directory-imports.mjs (1 hunks)
  • build/fix-telemetry-imports.mjs (1 hunks)
  • build/postDebugWebTest.js (1 hunks)
  • build/preDebugWebTest.js (2 hunks)
  • build/preLaunchWebTest.js (2 hunks)
  • build/remove-js-extensions.mjs (1 hunks)
  • build/util.js (1 hunks)
  • gulpfile.js (5 hunks)
  • package.json (5 hunks)
  • src/extension.node.ts (3 hunks)
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (4 hunks)
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (8 hunks)
  • src/notebooks/deepnote/deepnoteDataConverter.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/kernels/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

src/kernels/**/*.ts: Use event-driven updates (EventEmitter) for state changes
Monitor and dispose pending promises to prevent leaks during teardown
Use WeakRef/weak references for notebook/object backreferences to avoid memory leaks
Respect CancellationToken in all async operations

Files:

  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
**/*.{test,spec}.ts

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

In unit tests, when a mock is returned from a promise, ensure the mocked instance has an undefined then property to avoid hanging tests

Files:

  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/kernels/{jupyter,raw}/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

All session implementations must conform to IKernelSession

Files:

  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/kernels/raw/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Raw sessions must use ZeroMQ socket communication

Files:

  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
🧬 Code graph analysis (14)
src/extension.node.ts (1)
src/platform/logging/index.ts (1)
  • logger (35-48)
build/fix-directory-imports.mjs (2)
build/add-js-extensions.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (29-29)
  • entries (30-30)
  • fullPath (33-33)
  • content (77-77)
  • modified (50-50)
  • changeCount (51-51)
  • tsFiles (70-70)
  • totalFilesChanged (73-73)
  • newContent (78-78)
  • relativePath (84-84)
build/fix-telemetry-imports.mjs (16)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (16-16)
  • entries (17-17)
  • fullPath (20-20)
  • content (66-66)
  • modified (35-35)
  • changeCount (36-36)
  • pattern (41-41)
  • tsFiles (59-59)
  • totalFilesChanged (62-62)
  • totalImportsFixed (63-63)
  • newContent (67-67)
  • relativePath (73-73)
build/preDebugWebTest.js (2)
build/preLaunchWebTest.js (3)
  • __filename (10-10)
  • __dirname (11-11)
  • startJupyter (13-34)
build/webTestReporter.js (3)
  • __filename (19-19)
  • __dirname (20-20)
  • settingsFile (22-22)
build/remove-js-extensions.mjs (1)
build/add-js-extensions.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (29-29)
  • entries (30-30)
  • fullPath (33-33)
  • content (77-77)
  • modified (50-50)
  • changeCount (51-51)
  • tsFiles (70-70)
  • totalFilesChanged (73-73)
  • newContent (78-78)
  • relativePath (84-84)
build/fix-telemetry-imports.mjs (1)
build/fix-directory-imports.mjs (15)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (24-24)
  • entries (25-25)
  • fullPath (28-28)
  • content (70-70)
  • modified (43-43)
  • changeCount (44-44)
  • tsFiles (63-63)
  • totalFilesChanged (66-66)
  • totalImportsFixed (67-67)
  • newContent (71-71)
  • relativePath (77-77)
build/postDebugWebTest.js (2)
build/add-js-extensions.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
build/remove-js-extensions.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
gulpfile.js (2)
build/postDebugWebTest.js (3)
  • __filename (8-8)
  • __dirname (9-9)
  • file (12-12)
build/ci/postInstall.js (4)
  • __filename (14-14)
  • __dirname (15-15)
  • file (120-120)
  • packageLock (142-142)
src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (1)
src/kernels/helpers.unit.test.ts (2)
  • crateMockedPythonApi (23-39)
  • whenKnownEnvironments (40-51)
build/constants.js (1)
gulpfile.js (1)
  • isCI (28-28)
build/preLaunchWebTest.js (1)
src/test/datascience/jupyterServer.node.ts (1)
  • startJupyter (139-154)
build/util.js (8)
build/add-js-extensions.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
build/fix-directory-imports.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
build/fix-telemetry-imports.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
build/postDebugWebTest.js (3)
  • __filename (8-8)
  • __dirname (9-9)
  • file (12-12)
build/preDebugWebTest.js (2)
  • __filename (11-11)
  • __dirname (12-12)
build/remove-js-extensions.mjs (2)
  • __filename (9-9)
  • __dirname (10-10)
build/launchWebUtils.js (2)
  • __filename (15-15)
  • __dirname (16-16)
build/webTestReporter.js (3)
  • __filename (19-19)
  • __dirname (20-20)
  • filename (33-33)
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (2)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/kernels/raw/session/rawSessionConnection.node.ts (2)
  • RawSessionConnection (28-200)
  • kernel (84-86)
src/notebooks/deepnote/deepnoteDataConverter.ts (1)
src/platform/common/uuid.ts (1)
  • uuidUtils (64-66)
build/add-js-extensions.mjs (2)
build/fix-directory-imports.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (24-24)
  • entries (25-25)
  • fullPath (28-28)
  • content (70-70)
  • modified (43-43)
  • changeCount (44-44)
  • pattern (49-49)
  • tsFiles (63-63)
  • newContent (71-71)
  • relativePath (77-77)
build/remove-js-extensions.mjs (13)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (16-16)
  • entries (17-17)
  • fullPath (20-20)
  • content (67-67)
  • modified (35-35)
  • changeCount (36-36)
  • tsFiles (60-60)
  • newContent (68-68)
  • relativePath (74-74)
🪛 Biome (2.1.2)
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts

[error] 208-208: Do not add then to an object.

(lint/suspicious/noThenProperty)

🪛 GitHub Actions: CD
src/notebooks/deepnote/deepnoteDataConverter.ts

[error] 15-15: Cannot find module 'vega-lite/types_unstable' or its corresponding type declarations.

🪛 GitHub Actions: CI
src/notebooks/deepnote/deepnoteDataConverter.ts

[error] 15-15: Cannot find module 'vega-lite/types_unstable' or its corresponding type declarations. (TS2307)

🪛 GitHub Check: TypeCheck
src/notebooks/deepnote/deepnoteDataConverter.ts

[failure] 15-15:
Cannot find module 'vega-lite/types_unstable' or its corresponding type declarations.


[failure] 15-15:
Cannot find module 'vega-lite/types_unstable' or its corresponding type declarations.

🔇 Additional comments (23)
src/extension.node.ts (2)

54-55: LGTM: ESM import pattern is correct.

The node:os import follows Node.js ESM conventions.


181-201: Logging unified as suggested.

Both tryGetUsername() and tryGetHomePath() now route through the centralized logger instead of console.info. This addresses the previous review feedback and ensures consistent PII handling.

build/util.js (1)

4-23: ESM conversion looks correct.

The imports, __filename/__dirname setup, and exports are properly structured. Past review comments regarding redundant imports have been addressed.

build/constants.js (1)

4-6: ESM conversion is correct.

Re-export and constant definitions are properly structured.

src/notebooks/deepnote/deepnoteDataConverter.ts (3)

29-29: LGTM!

UUID import correctly uses the wrapper module for testability.


171-171: LGTM!

Correctly uses the UUID wrapper.


15-15: Import statement is correct; error is environment-specific.

The import path vega-lite/types_unstable is valid for vega-lite 6.4.1, correctly specified in package.json and lock file. The TypeScript error occurs because node_modules isn't cloned into the sandbox environment—this won't occur in your actual build when dependencies are installed via npm install.

The code requires no changes.

Likely an incorrect or invalid review comment.

package.json (1)

5-5: LGTM: ESM migration and package script update

Line 5 correctly enables ES modules project-wide. Line 2452's --no-dependencies flag is appropriate since dependencies are bundled via esbuild.

Also applies to: 2452-2452

gulpfile.js (2)

9-26: LGTM: ES module migration

Import statements and __filename/__dirname derivation follow standard ESM patterns.


73-73: Consistent UTF-8 encoding and proper dynamic import

Explicit 'utf-8' encoding now applied uniformly across file reads. Dynamic import at line 255 correctly handles the compiled telemetry generator module.

Also applies to: 110-110, 255-255, 274-274, 276-276, 284-284

src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (2)

14-15: Cleaner Python API mock setup

Using crateMockedPythonApi and whenKnownEnvironments improves test isolation and initializes the module-level Python API that helper functions require.

Also applies to: 28-28, 34-36


263-296: Richer mocks support helper functions

Mock environments now include environment.name, environment.folderUri, and executable.uri metadata that helper functions require. Using whenKnownEnvironments properly configures the Python API. Simplified quickpick selection reduces brittleness.

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (3)

34-41: ESM utilities correctly configured.

The getDirname and createRequire setup properly bridges ESM and CommonJS for loading @jupyterlab/services.


43-87: Async iterators now terminate (good fix), but may be too minimal.

The iterators correctly terminate after one empty message, fixing the infinite loop issue. However, tests expecting realistic ZeroMQ message sequences might need more than one empty message. Consider whether the mock should yield kernel-ready signals or other test-specific messages.


110-116: esmock properly injects ZeroMQ mock.

This correctly addresses the ESM mocking requirement, replacing unreliable require.cache manipulation with proper module stubbing.

build/preDebugWebTest.js (1)

19-27: PID temp directory handling looks good

Ensuring ../temp exists before writing deepnote.pid removes the previous failure mode when the directory was missing; fine to keep this synchronous in a short-lived build script.

build/postDebugWebTest.js (1)

4-9: ESM boilerplate is consistent

fileURLToPath(import.meta.url) plus path.dirname(__filename) matches the pattern used elsewhere; no issues here.

build/preLaunchWebTest.js (1)

13-33: ESM migration and jupyterServer import look correct

The startJupyter export preserves the previous behavior, and the .js extension on jupyterServer.node.js should satisfy Node’s ESM resolution.

build/remove-js-extensions.mjs (2)

38-55: Regex removal logic is safe for ./ and ../ paths.

The two patterns correctly strip .js from relative from and import() specifiers (including multi-level ../ prefixes) without touching bare package imports. No issues from the earlier concern about ../ handling.


58-87: Entrypoint and reporting look good.

File processing, change counting, and error handling are straightforward and side‑effect free beyond the intended rewrites.

build/add-js-extensions.mjs (2)

15-66: Multi-line import handling and .d.ts exclusion look correct.

The updated importPatterns cover multi-line static imports/exports and dynamic import/await import while still constraining to ./ / ../ paths, and getAllTsFiles now skips .d.ts, which avoids touching declarations. This script pairs cleanly with the other fixup tools.


68-92: Processing loop and counters are straightforward.

Per-file processing, aggregation, and logging are clear and consistent with the other build scripts; nothing concerning here.

build/fix-directory-imports.mjs (1)

61-85: CLI flow and logging are consistent with the other tools.

Traversal, update, and summary output are coherent and match the pattern used in the other build scripts.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5908dd0 and e474b7e.

📒 Files selected for processing (1)
  • src/notebooks/deepnote/deepnoteDataConverter.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/notebooks/deepnote/deepnoteDataConverter.ts (1)
src/platform/common/uuid.ts (1)
  • uuidUtils (64-66)
🔇 Additional comments (3)
src/notebooks/deepnote/deepnoteDataConverter.ts (3)

30-30: LGTM—wrapper pattern for ESM testability.

Change from direct generateUuid import to uuidUtils wrapper aligns with ESM migration strategy for easier test mocking.


172-172: LGTM—consistent with wrapper pattern.

Updated to uuidUtils.generateUuid() following the import change.


366-389: LGTM—improved typing and immutability.

Refactored with explicit type aliases and Immer's produce for safer mutations. Defensive config initialization on line 383 prevents undefined access. Type cast on line 389 is sound (subtype → supertype).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/notebooks/controllers/preferredKernelConnectionService.node.ts (1)

69-88: Precedence bug fixed; double-check .venv vs .conda priority

The added parentheses and (localEnvs.length ? localEnvs[0] : undefined) fallback fix the earlier || / ?: precedence issue and make the selection chain behave as intended.

One subtle point: the comment says “Give preference to .venv over .conda”, but the current ordering picks a Conda .conda environment before a VirtualEnv/VirtualEnvWrapper .venv. If you want any .venv to win over .conda, consider moving the VirtualEnv/VirtualEnvWrapper branch above the Conda branch or updating the comment to match the actual priority.

src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (1)

635-669: Consider tightening the error assertion for consistency.

Line 667 checks for the generic substring 'empty', while the equivalent test in the Copy Table suite (line 454) uses the more specific 'dataframe is empty'. For consistency and to avoid false positives, consider using the same specific substring here.

Apply this diff:

-                assert.include((error as Error).message, 'empty');
+                assert.include((error as Error).message, 'dataframe is empty');
src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (1)

27-65: Async setup + test subclass pattern looks solid and matches mocking guidelines

The async setup that wires getInterpreterInfoStub into the installer, constructs both installer and the test-only subclass, and explicitly clears then on mocked instances keeps the tests isolated and avoids the Promise-thenable pitfall described in the unit-test guidelines. As per coding guidelines.

src/kernels/execution/notebookUpdater.ts (1)

24-52: Guard update/applyEdit errors so the returned promise always settles.

If update(edit) throws synchronously or its returned promise rejects, execution never reaches the workspace.applyEdit call, so deferred.resolve/deferred.reject are never invoked and chainWithPendingUpdatesImpl can return a never‑resolving promise (the outer aggregatedPromise.catch(noop) does not touch deferred). This is a pre‑existing issue but still worth fixing.

You can wrap the body in try/catch so every path settles deferred while still chaining after prior updates, e.g.:

-    const pendingUpdates = pendingCellUpdates.has(notebook) ? pendingCellUpdates.get(notebook)! : Promise.resolve();
-    const deferred = createDeferred<boolean>();
-    const aggregatedPromise = pendingUpdates
-        // We need to ensure the update operation gets invoked after previous updates have been completed.
-        // This way, the callback making references to cell metadata will have the latest information.
-        // Even if previous update fails, we should not fail this current update.
-        .finally(async () => {
-            const edit = new WorkspaceEdit();
-            const result = update(edit);
-            if (isPromise(result)) {
-                await result;
-            }
-            await workspace.applyEdit(edit).then(
-                (result) => deferred.resolve(result),
-                (ex) => deferred.reject(ex)
-            );
-        })
-        .catch(noop);
+    const pendingUpdates = pendingCellUpdates.has(notebook)
+        ? pendingCellUpdates.get(notebook)!
+        : Promise.resolve();
+    const deferred = createDeferred<boolean>();
+    const aggregatedPromise = pendingUpdates
+        // Ensure this update runs after previous ones, regardless of their success.
+        .catch(noop)
+        .then(async () => {
+            const edit = new WorkspaceEdit();
+            try {
+                const result = update(edit);
+                if (isPromise(result)) {
+                    await result;
+                }
+                const applied = await workspace.applyEdit(edit);
+                deferred.resolve(applied);
+            } catch (ex) {
+                deferred.reject(ex);
+            }
+        });
     pendingCellUpdates.set(notebook, aggregatedPromise);
     return deferred.promise;
 }
src/platform/interpreter/installer/poetryInstaller.unit.test.ts (1)

46-80: Mirror the full fileUtils.node surface by stubbing async pathExists as well

The fileUtilsMock correctly stubs shellExecute, arePathsSame, pathExistsSync, readFileSync, and getPythonSetting, but the production fileUtils.node also exports an async pathExists that Poetry.getEnvListCached uses. If the installer ever exercises that path, these tests could fall back to the real filesystem.

To keep the tests fully hermetic and consistent with poetry.unit.test.ts, add an async pathExists stub:

-        const fileUtilsMock = {
-            shellExecute,
-            arePathsSame,
-            pathExistsSync,
-            readFileSync,
-            getPythonSetting
-        };
+        const fileUtilsMock = {
+            shellExecute,
+            arePathsSame,
+            pathExistsSync,
+            readFileSync,
+            getPythonSetting,
+            pathExists: () => Promise.resolve(true)
+        };
♻️ Duplicate comments (13)
src/test/datascience/.env (1)

1-2: Add trailing newline.

This issue has been flagged in prior reviews; add a blank line at EOF.

 VSCODE_JUPYTER_ENV_TEST_VAR1=FOO2
 VSCODE_JUPYTER_ENV_TEST_VAR2=BAR2
+
src/platform/common/uuid.ts (1)

68-70: Past review concern addressed

The delegation wrapper now calls uuidUtils.generateUuid() at runtime, making test stubbing effective. Arrow function achieves the same goal as the suggested regular function.

src/notebooks/deepnote/deepnoteTreeItem.ts (2)

93-125: Guard updateVisualFields against null data.

Lines 107 and 116 cast this.data without checking null, same issue as the constructor. If called after setting data to null, this throws.

 public updateVisualFields(): void {
     if (this.type === DeepnoteTreeItemType.Loading) {
         this.label = 'Loading…';
         this.tooltip = 'Loading…';
         this.description = '';
         this.iconPath = new ThemeIcon('loading~spin');
         return;
     }
+    if (!this.data) {
+        throw new Error(`Data cannot be null for ${this.type} items`);
+    }

Also note: this method duplicates the constructor's inline logic. Consider extracting shared logic if ESM constraints permit.


36-78: Add null guards for non-loading items.

Type signature allows data: null for any item type, but lines 45, 48, 61, 64, 70, 74 cast and access properties without null checks. If a non-loading item is created with null data, this throws at runtime.

Add a guard:

 } else {
+    if (!this.data) {
+        throw new Error(`Data cannot be null for ${this.type} items`);
+    }
     // getTooltip() inline
     if (this.type === DeepnoteTreeItemType.ProjectFile) {

Or narrow the type via overloads so non-loading items require non-null data.

build/remove-js-extensions.mjs (1)

41-46: Regex still misses ../ paths.

Pattern \.\/? only matches ./foo.js, not ../foo.js or deeper relative paths. Your comment mentions ../bar/index.js but it won't be matched.

Apply this fix:

     const patterns = [
         // import ... from './path.js' or '../path.js'
-        /(\bfrom\s+['"])(\.\/?[^'"]+)\.js(['"])/g,
+        /(\bfrom\s+['"])(\.{1,2}\/[^'"]+)\.js(['"])/g,
         // import('./path.js') or import('../path.js')
-        /(\bimport\s*\(\s*['"])(\.\/?[^'"]+)\.js(['"])/g
+        /(\bimport\s*\(\s*['"])(\.{1,2}\/[^'"]+)\.js(['"])/g
     ];
build/fix-telemetry-imports.mjs (1)

5-10: Redundant dirname import.

Line 7 imports dirname separately when path already provides it.

 import { promises as fs } from 'fs';
 import path from 'path';
 import { fileURLToPath } from 'url';
-import { dirname } from 'path';

 const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
+const __dirname = path.dirname(__filename);
src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (1)

15-22: Type query fix resolves the previous type-only import issue; remaining anys are optional

Using typeof import('./uvInstaller.node').UvInstaller for UvInstallerClass avoids the earlier 'only refers to a type' problem when UvInstaller is imported with import type. The loose any types on TestableUvInstallerClass and testableInstaller are fine for tests, but if you still want stricter typing you can mirror the earlier suggestion of defining a constructor type alias and InstanceType for the test subclass.

src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (1)

31-41: Disambiguate the two sandbox instances

You now have a top‑level sandbox for the outer suite and another sandbox in the addBlock suite, with identical names but different lifecycles. It works due to scoping, but it’s easy to misread and accidentally mix them up later; consider renaming one or adding a short comment to clarify which sandbox is used where.

Also applies to: 330-336

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (1)

199-259: Kernel mock wiring: ts‑mockito stubs don’t drive the object under test.

createKernel builds a rich plain kernelObj and has jupyterLabKernel.KernelConnection return that, but it also creates a ts‑mockito kernel and returns the mock from createKernel(). All the when(kernel.… ) stubs in this file operate on the ts‑mockito mock, while the production code talks to kernelObj, so those stubs never affect RawSessionConnection behavior (notably in the cancellation/time‑out tests).

You probably want one of:

  • Make KernelConnection return the ts‑mockito instance, and drive everything via when(...) on that instance; or
  • Drop the ts‑mockito kernel entirely and have tests interact with kernelObj directly (e.g., by exposing it or threading it through).

Right now this split is misleading and risks tests silently asserting the wrong behavior.

#!/bin/bash
# Quickly list where `kernel.` is stubbed/verified in this test file
rg -n "when\\(kernel\\." src/kernels/raw/session/rawSessionConnection.node.unit.test.ts -n -C3
src/standalone/intellisense/resolveCompletionItem.unit.test.ts (1)

134-141: Document that the cancellation stub intentionally ignores cancellation

This raceCancellation stub just returns the original promise, so tests never exercise a CancellationError path even if production code does. A short comment here stating that this is intentional for these unit tests would prevent confusion when cancellation behavior evolves.

src/platform/interpreter/installer/poetryInstaller.unit.test.ts (2)

27-27: Avoid any for poetryInstaller to keep tests aligned with the real API

poetryInstaller is still typed as any. Consider giving it a concrete type (e.g. a type‑only import from ../../../platform/interpreter/installer/poetryInstaller.node) so the test compiles against the real installer surface and catches API drifts at compile time.

For example:

type PoetryInstallerApi = import('../../../platform/interpreter/installer/poetryInstaller.node').PoetryInstaller;
let poetryInstaller: PoetryInstallerApi;

and cast the TestInstaller instance to PoetryInstallerApi when assigning.


96-123: Capture the esmock module for purge and avoid redundant sinon.restore

You already note in comments that esmock.purge should target the module, not the instance, but you don’t keep a module reference and you also call sinon.restore() both via a disposable and explicitly in teardown.

To tighten this up:

  1. Capture the poetryInstaller module at suite scope and purge it in teardown:
-    let poetryInstaller: any;
+    let poetryInstaller: any;
+    let poetryInstallerModule: any;
@@
-        const module = await esmock('../../../platform/interpreter/installer/poetryInstaller.node', {
+        poetryInstallerModule = await esmock('../../../platform/interpreter/installer/poetryInstaller.node', {
             '../../../platform/interpreter/installer/poetry.node': poetryNode,
             '../../../platform/common/platform/fileUtils.node': fileUtilsMock
         });
-        // Safely remove 'then' property to prevent promise-like behavior
+        // Safely remove any existing 'then' to avoid thenable/promise-like behavior in tests
-        const PoetryInstaller = module.PoetryInstaller;
+        const PoetryInstaller = poetryInstallerModule.PoetryInstaller;
@@
-    teardown(() => {
-        disposables = dispose(disposables);
-        sinon.restore();
-        // esmock.purge(poetryInstaller); // poetryInstaller is an instance, not the module.
-        // We should purge the module if we kept a reference, but esmock might handle it if we don't reuse it?
-        // Better to purge. But I don't have the module reference here easily unless I store it.
-        // Actually esmock.purge is for the module.
-    });
+    teardown(() => {
+        disposables = dispose(disposables);
+        if (poetryInstallerModule) {
+            esmock.purge(poetryInstallerModule);
+            poetryInstallerModule = undefined;
+        }
+    });
  1. Given you already push a disposable that calls sinon.restore(), you can rely on that and drop the explicit sinon.restore() call in teardown (or vice versa), so sinon isn’t restored twice.

Also applies to: 135-141

src/platform/interpreter/installer/poetry.unit.test.ts (1)

123-156: Tighten Poetry typing, add async pathExists, and purge using the module object

In the “Poetry binary is located correctly” suite:

  • Poetry is still typed as any.
  • The fileUtils.node stub omits async pathExists, even though Poetry.getEnvListCached uses it.
  • esmock.purge(Poetry) is called with the Poetry export instead of the module object returned by esmock.

You can address all three at once:

-suite('Poetry binary is located correctly', async () => {
-    let Poetry: any;
+suite('Poetry binary is located correctly', async () => {
+    type PoetryCtor = typeof import('../../../platform/interpreter/installer/poetry.node').Poetry;
+    let Poetry: PoetryCtor;
+    let poetryModule: any;
@@
-    setup(async () => {
+    setup(async () => {
@@
-        const module = await esmock('../../../platform/interpreter/installer/poetry.node', {
+        poetryModule = await esmock('../../../platform/interpreter/installer/poetry.node', {
             '../../../platform/common/platform/fileUtils.node': {
                 shellExecute,
                 getPythonSetting,
                 pathExistsSync,
                 readFileSync,
-                arePathsSame: (p1: string, p2: string) => p1 === p2 // Simple mock for arePathsSame
+                pathExists: () => Promise.resolve(true),
+                arePathsSame: (p1: string, p2: string) => p1 === p2 // Simple mock for arePathsSame
             },
             '../../../platform/common/utils/platform.node': {
                 getUserHomeDir
             }
         });
-        Poetry = module.Poetry;
+        Poetry = poetryModule.Poetry;
@@
-    teardown(() => {
-        sinon.restore();
-        esmock.purge(Poetry);
-    });
+    teardown(() => {
+        sinon.restore();
+        if (poetryModule) {
+            esmock.purge(poetryModule);
+            poetryModule = undefined;
+        }
+    });

This keeps the test coupled to the real Poetry constructor, ensures no accidental filesystem access via pathExists, and purges the correct esmock module between tests.

Also applies to: 138-149

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e474b7e and 8b31e74.

📒 Files selected for processing (35)
  • build/fix-telemetry-imports.mjs (1 hunks)
  • build/preDebugWebTest.js (2 hunks)
  • build/preLaunchWebTest.js (2 hunks)
  • build/remove-js-extensions.mjs (1 hunks)
  • gulpfile.js (5 hunks)
  • package.json (6 hunks)
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (4 hunks)
  • src/kernels/execution/notebookUpdater.ts (2 hunks)
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts (5 hunks)
  • src/kernels/kernelDependencyService.node.ts (4 hunks)
  • src/kernels/raw/session/rawSessionConnection.node.ts (3 hunks)
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (7 hunks)
  • src/kernels/serviceRegistry.node.ts (1 hunks)
  • src/notebooks/controllers/ipywidgets/scriptSourceProvider/ipyWidgetScriptSource.ts (2 hunks)
  • src/notebooks/controllers/preferredKernelConnectionService.node.ts (3 hunks)
  • src/notebooks/deepnote/deepnoteDataConverter.ts (4 hunks)
  • src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (17 hunks)
  • src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (2 hunks)
  • src/notebooks/deepnote/deepnoteTreeItem.ts (2 hunks)
  • src/notebooks/deepnote/deepnoteTreeItem.unit.test.ts (2 hunks)
  • src/platform/common/platform/fileUtils.node.ts (2 hunks)
  • src/platform/common/utils/platform.node.ts (1 hunks)
  • src/platform/common/utils/platform.ts (2 hunks)
  • src/platform/common/uuid.ts (2 hunks)
  • src/platform/errors/index.ts (1 hunks)
  • src/platform/interpreter/globalPythonExePathService.node.ts (2 hunks)
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts (2 hunks)
  • src/platform/interpreter/installer/poetry.unit.test.ts (8 hunks)
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts (3 hunks)
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (1 hunks)
  • src/platform/ioc/reflectMetadata.ts (1 hunks)
  • src/standalone/intellisense/resolveCompletionItem.unit.test.ts (7 hunks)
  • src/test/datascience/.env (1 hunks)
  • src/test/vscode-mock.ts (2 hunks)
  • src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
src/platform/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

src/platform/**/*.ts: Use Inversify decorators for DI: annotate classes with @Injectable() and inject dependencies with @Inject(Token)
Use the centralized logger (import { logger } from '../platform/logging') instead of console.log for application logging

Files:

  • src/platform/common/uuid.ts
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts
  • src/platform/interpreter/installer/poetry.unit.test.ts
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts
  • src/platform/interpreter/globalPythonExePathService.node.ts
  • src/platform/ioc/reflectMetadata.ts
  • src/platform/common/utils/platform.node.ts
  • src/platform/errors/index.ts
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts
  • src/platform/common/platform/fileUtils.node.ts
  • src/platform/common/utils/platform.ts
**/*.{test,spec}.ts

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

In unit tests, when a mock is returned from a promise, ensure the mocked instance has an undefined then property to avoid hanging tests

Files:

  • src/webviews/extension-side/dataframe/dataframeController.unit.test.ts
  • src/notebooks/deepnote/deepnoteTreeItem.unit.test.ts
  • src/notebooks/deepnote/deepnoteSerializer.unit.test.ts
  • src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts
  • src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts
  • src/platform/interpreter/installer/poetry.unit.test.ts
  • src/platform/interpreter/installer/uvInstaller.node.unit.test.ts
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts
  • src/platform/interpreter/installer/poetryInstaller.unit.test.ts
  • src/standalone/intellisense/resolveCompletionItem.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
src/platform/**/*.node.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

src/platform/**/*.node.ts: Provide Node.js-specific implementations in .node.ts files (e.g., FileSystem with fs-extra, PlatformService with OS detection)
Desktop implementations may use Node capabilities (fs-extra, process spawning, native modules) consistent with their responsibilities

Files:

  • src/platform/interpreter/globalPythonExePathService.node.ts
  • src/platform/common/utils/platform.node.ts
  • src/platform/common/platform/fileUtils.node.ts
src/kernels/execution/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Notebook-level execution must enqueue cells via CellExecutionQueue and manage per-cell lifecycles through CellExecution

Files:

  • src/kernels/execution/notebookUpdater.ts
src/kernels/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

src/kernels/**/*.ts: Use event-driven updates (EventEmitter) for state changes
Monitor and dispose pending promises to prevent leaks during teardown
Use WeakRef/weak references for notebook/object backreferences to avoid memory leaks
Respect CancellationToken in all async operations

Files:

  • src/kernels/execution/notebookUpdater.ts
  • src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts
  • src/kernels/kernelAutoReConnectMonitor.unit.test.ts
  • src/kernels/serviceRegistry.node.ts
  • src/kernels/kernelDependencyService.node.ts
  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
src/platform/**/ioc/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Register platform services in the IoC container using ServiceManager (e.g., serviceManager.addSingleton(Token, Impl)) within a registerTypes function

Files:

  • src/platform/ioc/reflectMetadata.ts
src/kernels/{kernelFinder.ts,serviceRegistry.{node,web}.ts}

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Finders must be registered with the KernelFinder on startup

Files:

  • src/kernels/serviceRegistry.node.ts
src/kernels/serviceRegistry.node.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Node service registry must register raw kernel components and enable filesystem-based discovery

Files:

  • src/kernels/serviceRegistry.node.ts
src/kernels/serviceRegistry.{node,web}.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Use dependency injection for services to enable testability and platform variance

Files:

  • src/kernels/serviceRegistry.node.ts
src/kernels/{jupyter,raw}/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

All session implementations must conform to IKernelSession

Files:

  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
src/kernels/raw/session/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/kernel.instructions.md)

Raw sessions must use ZeroMQ socket communication

Files:

  • src/kernels/raw/session/rawSessionConnection.node.unit.test.ts
  • src/kernels/raw/session/rawSessionConnection.node.ts
src/platform/common/platform/**/*.ts

📄 CodeRabbit inference engine (.github/instructions/platform.instructions.md)

Expose file system operations through IFileSystem/IFileSystemNode and platform data via IPlatformService instead of direct APIs

Files:

  • src/platform/common/platform/fileUtils.node.ts
🧬 Code graph analysis (24)
src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (1)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
build/fix-telemetry-imports.mjs (3)
build/remove-js-extensions.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (16-16)
  • entries (17-17)
  • fullPath (20-20)
  • content (67-67)
  • modified (35-35)
  • changeCount (36-36)
  • tsFiles (60-60)
  • totalFilesChanged (63-63)
  • newContent (68-68)
  • relativePath (74-74)
build/fix-directory-imports.mjs (15)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (24-24)
  • entries (25-25)
  • fullPath (28-28)
  • content (70-70)
  • modified (43-43)
  • changeCount (44-44)
  • pattern (49-49)
  • tsFiles (63-63)
  • totalFilesChanged (66-66)
  • newContent (71-71)
  • relativePath (77-77)
build/add-js-extensions.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (29-29)
  • entries (30-30)
  • fullPath (33-33)
  • content (77-77)
  • modified (50-50)
  • changeCount (51-51)
  • tsFiles (70-70)
  • totalFilesChanged (73-73)
  • newContent (78-78)
  • relativePath (84-84)
src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (1)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (2)
src/platform/common/types.ts (1)
  • IDisposable (211-213)
src/test/vscode-mock.ts (1)
  • mockedVSCodeNamespaces (15-15)
src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts (1)
src/platform/interpreter/installer/pipenv.node.ts (1)
  • isPipenvEnvironmentRelatedToFolder (104-118)
src/platform/interpreter/installer/poetry.unit.test.ts (4)
src/platform/interpreter/installer/poetry.node.ts (2)
  • isPoetryEnvironment (83-91)
  • Poetry (97-297)
src/platform/common/platform/fileUtils.node.ts (5)
  • shellExecute (21-26)
  • getPythonSetting (72-76)
  • pathExistsSync (38-40)
  • readFileSync (46-48)
  • isVirtualenvEnvironment (105-116)
src/platform/common/utils/platform.ts (1)
  • getOSType (36-36)
src/platform/common/utils/platform.node.ts (1)
  • getUserHomeDir (31-39)
src/platform/interpreter/installer/uvInstaller.node.unit.test.ts (2)
src/platform/common/process/types.node.ts (1)
  • IProcessService (47-51)
src/platform/interpreter/installer/moduleInstaller.node.ts (1)
  • ExecutionInstallArgs (30-35)
src/platform/interpreter/globalPythonExePathService.node.ts (1)
src/platform/common/platform/fs-paths.node.ts (1)
  • getDisplayPath (27-32)
build/preDebugWebTest.js (2)
build/preLaunchWebTest.js (2)
  • __dirname (10-10)
  • startJupyter (12-33)
build/webTestReporter.js (2)
  • __dirname (20-20)
  • settingsFile (22-22)
src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (2)
src/test/vscode-mock.ts (1)
  • resetVSCodeMocks (57-305)
src/kernels/helpers.unit.test.ts (2)
  • crateMockedPythonApi (23-39)
  • whenKnownEnvironments (40-51)
src/platform/common/utils/platform.node.ts (2)
src/platform/common/variables/types.ts (1)
  • EnvironmentVariables (8-8)
src/platform/common/utils/platform.ts (1)
  • platformUtils (29-32)
src/platform/errors/index.ts (1)
src/platform/errors/types.ts (2)
  • TelemetryErrorProperties (112-148)
  • getErrorCategory (59-64)
src/notebooks/deepnote/deepnoteDataConverter.ts (1)
src/platform/common/uuid.ts (1)
  • uuidUtils (64-66)
src/notebooks/controllers/preferredKernelConnectionService.node.ts (1)
src/platform/interpreter/helpers.ts (1)
  • getEnvironmentType (87-90)
build/preLaunchWebTest.js (1)
src/test/datascience/jupyterServer.node.ts (1)
  • startJupyter (139-154)
src/platform/interpreter/installer/poetryInstaller.unit.test.ts (3)
src/platform/common/platform/fileUtils.node.ts (4)
  • shellExecute (21-26)
  • pathExistsSync (38-40)
  • readFileSync (46-48)
  • getPythonSetting (72-76)
src/platform/common/process/types.node.ts (2)
  • ShellOptions (40-40)
  • ExecutionResult (42-45)
src/platform/interpreter/installer/moduleInstaller.node.ts (1)
  • ExecutionInstallArgs (30-35)
src/test/vscode-mock.ts (5)
src/notebooks/controllers/notebookIPyWidgetCoordinator.ts (1)
  • onDidCloseNotebookDocument (173-180)
src/test/datascience/notebook/controllerPreferredService.ts (1)
  • onDidOpenNotebookDocument (370-393)
src/standalone/recommendation/extensionRecommendation.node.ts (1)
  • onDidOpenNotebookDocument (64-72)
src/platform/common/helpers.ts (1)
  • format (62-64)
src/platform/common/configSettings.ts (1)
  • initialize (223-251)
src/kernels/kernelDependencyService.node.ts (1)
src/test/mocks/vsc/index.ts (1)
  • CancellationTokenSource (114-125)
src/standalone/intellisense/resolveCompletionItem.unit.test.ts (3)
src/standalone/intellisense/kernelCompletionProvider.ts (3)
  • resolveCompletionItem (311-335)
  • resolveCompletionItem (484-487)
  • dispose (459-462)
src/standalone/intellisense/resolveCompletionItem.ts (2)
  • resolveCompletionItem (40-90)
  • maxPendingKernelRequests (28-28)
src/platform/common/utils/async.ts (4)
  • reject (123-127)
  • promise (128-130)
  • Deferred (86-95)
  • createDeferred (142-144)
build/remove-js-extensions.mjs (3)
build/fix-telemetry-imports.mjs (15)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (16-16)
  • entries (17-17)
  • fullPath (20-20)
  • content (66-66)
  • modified (35-35)
  • changeCount (36-36)
  • pattern (41-41)
  • tsFiles (59-59)
  • totalFilesChanged (62-62)
  • newContent (67-67)
  • relativePath (73-73)
build/fix-directory-imports.mjs (15)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (24-24)
  • entries (25-25)
  • fullPath (28-28)
  • content (70-70)
  • modified (43-43)
  • changeCount (44-44)
  • pattern (49-49)
  • tsFiles (63-63)
  • totalFilesChanged (66-66)
  • newContent (71-71)
  • relativePath (77-77)
build/add-js-extensions.mjs (14)
  • __filename (9-9)
  • __dirname (10-10)
  • rootDir (12-12)
  • srcDir (13-13)
  • files (29-29)
  • entries (30-30)
  • fullPath (33-33)
  • content (77-77)
  • modified (50-50)
  • changeCount (51-51)
  • tsFiles (70-70)
  • totalFilesChanged (73-73)
  • newContent (78-78)
  • relativePath (84-84)
src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (2)
src/platform/common/esmUtils.node.ts (1)
  • getDirname (13-15)
src/kernels/raw/session/rawSessionConnection.node.ts (2)
  • RawSessionConnection (25-193)
  • kernel (77-79)
src/platform/common/utils/platform.ts (1)
src/platform/common/utils/platform.node.ts (1)
  • platformUtils (19-21)
gulpfile.js (2)
build/ci/postInstall.js (4)
  • __filename (14-14)
  • __dirname (15-15)
  • file (120-120)
  • packageLock (142-142)
build/webTestReporter.js (2)
  • __filename (19-19)
  • __dirname (20-20)
src/notebooks/deepnote/deepnoteTreeItem.ts (2)
src/test/mocks/vsc/extHostedTypes.ts (1)
  • ThemeIcon (2094-2104)
src/platform/deepnote/deepnoteTypes.ts (2)
  • DeepnoteProject (12-12)
  • DeepnoteNotebook (18-18)
🪛 Biome (2.1.2)
src/notebooks/deepnote/deepnoteSerializer.unit.test.ts

[error] 216-216: Do not add then to an object.

(lint/suspicious/noThenProperty)

src/platform/interpreter/installer/poetryInstaller.unit.test.ts

[error] 91-91: Do not add then to an object.

(lint/suspicious/noThenProperty)


[error] 102-102: Do not add then to an object.

(lint/suspicious/noThenProperty)

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts

[error] 208-208: Do not add then to an object.

(lint/suspicious/noThenProperty)

🔇 Additional comments (63)
src/kernels/serviceRegistry.node.ts (1)

6-7: Import split looks correct and preserves behavior

Moving Identifiers to ../platform/common/constants and isPreReleaseVersion to the node-specific ../platform/constants.node matches the platform split elsewhere and doesn’t alter how registerTypes behaves. No further changes needed here.

src/platform/ioc/reflectMetadata.ts (2)

4-11: Previous feedback addressed.

Comment now correctly describes ESM import timing and reflect-metadata's internal safeguards.


13-13: Clean ESM import.

Previous ESLint comment removed; bare import syntax correct.

src/platform/interpreter/globalPythonExePathService.node.ts (2)

12-12: Node-specific import is appropriate.

The .node suffix aligns with the ESM migration and Node-specific implementation pattern.


91-96: Past issue properly resolved.

The await on fs.exists is now correct, and the boolean result is used in the conditional. Error message properly handles undefined paths.

package.json (7)

5-5: ESM module type declaration added.

Sets up project for ES modules. Ensure all source files (TypeScript-compiled to JavaScript) use ESM import/export rather than CommonJS.


2212-2212: MIME type updated to match Vega v6 runtime.

Correctly updated "application/vnd.vega.v5+json""application/vnd.vega.v6+json". This aligns with the installed Vega v6.2.0 and resolves the past review concern about content-type negotiation mismatches.


2545-2547: Vega major version updates verified compatible with ESM and react-vega.

Vega v6 is ESM-only (no CommonJS build), and react-vega ^7.7.1 supports both Vega and Vega-Lite. Past web search confirmed vega-embed v7 has no breaking API changes from v6, and Vega-Lite v6 uses stable APIs that are renderer-compatible. The migration requirements (ESM imports, updated toolchain) are being handled elsewhere in the PR.


2650-2650: esmock added as testing dependency for ESM mocking.

Appropriate for testing ESM modules. Present in both dependencies and devDependencies—verify this is intentional (likely should be devDependencies only).


2452-2452: Package script updated with --no-dependencies flag.

Verify that vsce package --no-dependencies is the correct approach for this extension's distribution. Ensure dependencies are bundled via the build process rather than declared in the VSIX manifest.


2479-2555: Codecov package successfully removed.

No occurrence of "codecov" in dependencies or devDependencies. Consistent with PR objective to use codecov CLI instead.


2511-2511: js-yaml 4.1.1 security patch verified.

The update fixes CVE-2025-64718, a prototype-pollution vulnerability in the YAML merge (<<) operator. The patch is legitimate and recommended.

src/platform/common/uuid.ts (2)

10-61: LGTM: Standard UUID v4 implementation

The IIFE correctly prefers crypto.randomUUID when available and provides a solid fallback using crypto.getRandomValues with proper version bits.


63-66: LGTM: Test-friendly wrapper pattern

The mutable uuidUtils object properly enables test stubbing in ESM.

src/notebooks/deepnote/deepnoteDataConverter.ts (4)

15-16: ts-ignore justified for migration phase.

The comment clearly explains the moduleResolution constraint. Acceptable trade-off given the broader .js extension requirements that node16 resolution would impose during ESM migration.


30-30: Clean ESM wrapper adoption.

Aligns with the testability pattern for ESM migration.


172-172: Consistent wrapper usage.

Correctly uses the uuidUtils wrapper imported on line 30.


366-390: Improved type safety with Immer-based patching.

The explicit type aliases and produce-based immutable patching are clearer than inline mutation. The config guard (lines 383-385) is good defensive coding.

Note: the cast to VegaLiteSpec on line 389 assumes the extended properties (height, width, autosize) are compatible with vega-lite's compile input, which is correct for the vega-lite API but bypasses TypeScript's structural checks.

src/kernels/deepnote/environments/deepnoteEnvironmentsView.unit.test.ts (3)

14-36: ESM mocking setup looks clean.

The new helper-based approach (crateMockedPythonApi, whenKnownEnvironments) simplifies Python API mocking and ensures proper cleanup through the disposables array.


293-296: Interpreter selection decoupled from internal IDs.

Returning the first quick pick item is more flexible than stubbing specific interpreter IDs and avoids coupling to helper transformation logic.


361-364: Assertions appropriately strengthened.

Checks for pythonInterpreter.uri and .id presence without coupling to transformed ID values. (Note: past review suggested .version; .id is equally valid here.)

src/notebooks/deepnote/deepnoteSerializer.unit.test.ts (2)

2-2: LGTM: Imports support new test scenario.

The added imports (when, NotebookDocument, mockedVSCodeNamespaces) are used correctly in the new test case.

Also applies to: 4-4, 10-10


213-239: LGTM: Test correctly implements fallback with proper mock safeguards.

The then: undefined property on line 216 is required per coding guidelines to prevent test hangs when the mock is returned from a promise. The static analysis warning is a false positive—this property is intentional.

Based on coding guidelines.

src/test/vscode-mock.ts (2)

4-4: LGTM: Exports enable test access to mocked VSCode surface.

Import additions and the public mockedVSCode export support the ESM test infrastructure.

Also applies to: 14-14


69-205: LGTM: Comprehensive mock setup supports ESM test infrastructure.

The extensive event emitters, dialog overloads, and workspace method mocks are necessary to provide test coverage for the VSCode API surface. While verbose, the multiple overloads ensure ts-mockito handles all parameter combinations correctly.

src/notebooks/deepnote/deepnoteTreeItem.unit.test.ts (1)

602-624: LGTM.

Test properly validates loading visuals now set by the constructor. Aligns with implementation changes.

src/kernels/kernelAutoReConnectMonitor.unit.test.ts (1)

103-118: Consistent timing pattern applied.

The test now properly flushes microtasks after each event: onDidStartKernel.fire()nextAsync()emit('connecting')nextAsync()emit('disconnected')nextAsync(). This pattern is consistently applied across all tests in this suite.

src/kernels/kernelDependencyService.node.ts (1)

115-173: Shadowing fix correctly applied.

The cancelTokenSource is now assigned to the outer variable (line 117) instead of shadowing with const. Non-null assertions at lines 119, 136, 151 are safe since they're inside the if (!promise) block where assignment is guaranteed. Line 162's optional chaining correctly handles the case when reusing a cached promise.

Based on learnings

src/notebooks/controllers/preferredKernelConnectionService.node.ts (1)

13-13: Node-specific getDisplayPath import looks correct

Switching to fs-paths.node matches the Node-side pattern used elsewhere and is appropriate for this controller.

src/webviews/extension-side/dataframe/dataframeController.unit.test.ts (2)

2-2: LGTM: verify import added for ts-mockito verification pattern.

The import supports the new verification approach used in line 632.


628-633: Mock setup confirmed—code is correct.

mockedVSCodeNamespaces.window is properly initialized as a ts-mockito mock in resetVSCodeMocks() via the generateMock('window') function at src/test/vscode-mock.ts:19-20. The verify() call on line 632 is fully compatible with this mock and will work as expected.

build/remove-js-extensions.mjs (1)

1-32: LGTM on setup and traversal.

The .d.ts exclusion on line 26 properly addresses previous feedback.

build/fix-telemetry-imports.mjs (1)

34-56: Regex patterns look correct.

The non-capturing groups (?:\.\.?\/)+ properly handle both ./ and ../ paths at any depth. Past regex issues have been addressed.

build/preDebugWebTest.js (2)

4-14: Clean ESM migration.

Standard pattern for __filename/__dirname in ESM is correctly applied.


22-26: Good defensive practice.

Creating the temp directory before writing the PID file prevents potential failures.

build/preLaunchWebTest.js (2)

4-11: ESM migration complete.

The .js extension on line 5 and path.dirname usage on line 10 correctly address previous feedback.


12-33: Function export looks good.

The ESM export syntax is correct, and the migration preserves existing logic.

src/platform/interpreter/installer/pipEnvInstaller.unit.test.ts (4)

17-18: ESM imports look good.

Proper use of esmock and type-only import.


25-25: Type safety restored.

Variable now properly typed as PipEnvInstaller instead of any.


30-49: ESM migration with esmock implemented correctly.

Async setup, dynamic module loading, and stub injection all follow the expected pattern. The stub's reference-equality check (===) on Uri objects works for this test design since tests pass the same constant references or different values to trigger failures.


61-63: Duplicate sinon.restore() removed.

The explicit sinon.restore() call has been removed from teardown as suggested in the previous review.

src/platform/common/platform/fileUtils.node.ts (2)

56-64: Delegation pattern correctly implemented.

Both pathExists and readFile now delegate through fileUtilsNodeUtils at runtime, enabling test stubbing.


4-4: fs-extra default import is correctly used and consistent with the codebase.

Default imports of fs-extra are already established throughout the codebase (test files, build scripts, and platform code). The pattern used in fileUtils.node.ts line 4 matches multiple other files and demonstrates the module is properly configured for ESM interop.

src/platform/common/utils/platform.node.ts (1)

18-25: Delegation pattern correctly implemented.

getEnvironmentVariable now delegates through platformUtils at runtime, enabling test stubbing.

src/platform/common/utils/platform.ts (1)

28-37: Delegation pattern correctly implemented.

Both getOSType and untildify delegate through platformUtils at runtime, enabling test stubbing.

src/platform/errors/index.ts (1)

8-8: Import cleanup looks good.

Removed unused WrappedError import appropriately.

gulpfile.js (3)

9-27: ESM imports and __filename/__dirname shim look correct

The import list and the fileURLToPath/dirname pattern re‑create __filename/__dirname cleanly for this ESM gulpfile; nothing stands out as problematic in the migration from the old require setup.

Please confirm your Gulp invocation is running under a Node setup that supports ESM gulpfiles (recent Gulp 4 + "type": "module"), so these imports are actually picked up at runtime.


69-83: Explicit UTF‑8 reads and JSON parsing are consistent and sensible

Using fs.readFileSync(..., 'utf-8') / .toString('utf-8') plus JSON.parse for translations, package-lock.json, package.json, telemetry files, and unhandledErrors.txt makes encoding explicit and aligns with the pattern in other build scripts; the updated call sites look correct and side‑effect‑free.

When you run the affected tasks (validateTranslationFiles, checkNpmDependencies, updatePackageJsonForBundle, validateTelemetry, validatePackageLockJson, verifyUnhandledErrors) on a clean checkout, double‑check that no unexpected file diffs or encoding glitches appear, especially on non‑UTF‑8 locale setups.

Also applies to: 104-158, 160-166, 168-203, 261-269, 271-279, 281-288


253-259: Dynamic import for the telemetry generator is an appropriate ESM adaptation

Wrapping telemetry generation in async function generateTelemetry() and loading ./out/telemetryGenerator.node.js via await import(...) with generator.default() is a reasonable way to keep this gulpfile ESM‑friendly while preserving the previous behavior.

Please verify that the built telemetry generator actually lands at out/telemetryGenerator.node.js (name and extension) so this specifier resolves correctly when the generateTelemetry task runs.

src/notebooks/controllers/ipywidgets/scriptSourceProvider/ipyWidgetScriptSource.ts (1)

5-5: Static import + cached jupyterLab assignment look correct.

Using a static ESM import and caching it onto this.jupyterLab in initialize() matches the ESM migration goals, and the new comment accurately describes the behavior (no longer claiming lazy loading). No further issues here.

Also applies to: 110-113

src/notebooks/deepnote/deepnoteNotebookCommandListener.unit.test.ts (2)

1002-1003: Chart block metadata assertions match updated semantics

Asserting that __deepnotePocket exists and its type is 'visualization' gives good coverage for the updated chart cell metadata; these expectations align with the surrounding checks and don’t need changes.


3-3: Review comment verified—no corrections needed

The code correctly avoids resolving mocked instances from promises. All thenResolve() calls resolve to plain values (undefined, true) or concrete VS Code objects, never to mock instances. The setup adheres to the unit-test guideline and prevents thenable mock hangs.

src/kernels/raw/session/rawSessionConnection.node.unit.test.ts (5)

4-4: ESM test setup with esmock and createRequire looks consistent.

Using getDirname(import.meta.url), createRequire for the JupyterLab kernel, and esmock('./rawSessionConnection.node.js', { zeromq: mockZmq }) in suiteSetup is a reasonable ESM‑friendly pattern for these tests.

Also applies to: 34-40, 89-92, 110-116


43-87: ZeroMQ mock now terminates async iterators—good.

The updated mockZmq Subscriber/Dealer async iterators yield once and then return done: true, which avoids the previous infinite‑loop risk while still exercising the consumer logic.


361-364: “After Start” suite skip + TODO are clear.

The suite.skip with explicit TODO and blocking‑reason comments is clear enough for a temporary disablement, assuming there’s a real tracking item behind build/feedback.md item 2.


204-248: Remove then: undefined from kernelObj.

The mock is returned synchronously from a constructor (line 256), never from a Promise. The coding guideline requiring then: undefined applies only when mocks flow through promise chains—this one doesn't. Removing it eliminates the Biome error and keeps the code clean.


317-359: Now I need to verify the actual test setup and how the kernel is wired:

Based on my analysis, I need to verify the actual implementation of the test setup and how the cancellation is handled. Let me search for the startKernel implementation to understand whether the kernel mocks are actually necessary for these tests to pass.

Skip stub mocking in active cancellation tests—the kernel mock from createKernel doesn't connect due to ZeroMQ esmock gap.

The two active tests at lines 339–352 and 353–359 stub kernel.requestKernelInfo(), but this stub has no effect since the kernel instance used by RawSessionConnection.startKernel() comes from createKernel wiring that esmock cannot intercept at the module boundary (as already documented in the suite's TODO). The tests still pass because cancellation handling runs independent of kernel method calls—the CancellationToken rejection path executes before or regardless of requestKernelInfo() invocation. However, the stubbing is misleading and unnecessary.

Remove the when(kernel.requestKernelInfo())… blocks from both active tests, or align them with the skipped tests by applying test.skip until the ZeroMQ mocking gap is resolved per build/feedback.md item 2.

src/kernels/raw/session/rawSessionConnection.node.ts (1)

165-176: Methods throw as designed; no external callers found that would break.

Verified via code search: setPath, setName, setType, and changeKernel are only delegated within BaseJupyterSessionConnection.ts itself. No external code calls these methods on session instances. RawJupyterSessionWrapper wraps raw sessions, while JupyterSessionWrapper wraps Jupyter sessions—they're used separately. Explicit throwing prevents silent failures and aligns with raw session constraints.

src/standalone/intellisense/resolveCompletionItem.unit.test.ts (4)

29-36: Typed async imports and test-scoped handles look solid

Importing Deferred as a type and tightening resolveCompletionItem / execCodeInBackgroundThreadStub typings align the tests with the real API and make future refactors safer. No issues here.

Also applies to: 49-52


77-83: ServiceContainerMock pattern and reset avoid cross‑test leakage

The ServiceContainerMock with a shared serviceContainerInstance plus resetting it in teardown keeps container state test‑local and fixes the earlier any typing. This wiring looks correct.

Also applies to: 167-171


85-133: Confirm async-utils esmock stub doesn’t drop RequestTimedoutError

The esmock setup for '../../platform/common/utils/async' provides createDeferred, sleep, and a custom raceTimeoutError, but does not expose RequestTimedoutError. If resolveCompletionItem imports RequestTimedoutError from this module, you may end up with it being undefined depending on how esmock composes stubs with originals. To be defensive, consider explicitly re‑exporting the real RequestTimedoutError in this stub (or confirming via docs/tests that esmock preserves unspecified exports).

Also applies to: 142-162


531-538: Python background‑exec Deferred wiring is correct and respects promise/mocking guideline

Using a Deferred<KernelMessage.IInspectReplyMsg['content']> with execCodeInBackgroundThreadStub returning resolveOutputs.promise, and resolving it with plain content objects, gives precise control over the Python path without returning mocked instances from promises (so no then pitfalls). Injecting serviceContainerInstance only in the Python setup and resetting it in the outer teardown also keeps this path isolated.

As per coding guidelines

Also applies to: 549-551, 574-581, 602-609

src/platform/interpreter/installer/poetry.unit.test.ts (1)

159-203: Poetry binary resolution tests nicely reflect Poetry.getPoetry behavior

The scenarios in these tests — missing pyproject.toml, invalid pyproject.toml, explicit custom poetry path, PATH‑based resolution, and fallback to the default ${HOME}/.poetry/bin/poetry — line up with the Poetry.getPoetry implementation (including use of getPythonSetting, pathExistsSync, readFileSync, getUserHomeDir, and shellExecute).

The stubs and expectations here look consistent and should give good coverage of the resolution logic.

Also applies to: 215-249

@Artmann
Copy link
Member Author

Artmann commented Nov 21, 2025

@coderabbitai I've resolved all your comments!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Tip

For best results, initiate chat on the files or code changes.

@Artmann Thank you for addressing all the feedback! The migration to ESM looks solid.

@Artmann Artmann marked this pull request as ready for review November 21, 2025 10:59
@Artmann Artmann requested a review from a team as a code owner November 21, 2025 10:59
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