Repository: microsoft/vscode-js-debug (TypeScript)

Issue:
step over / step into `eval` call fails when pauseForSourceMap is true
**Describe the bug**
When `pauseForSourceMap` is true and eval is called on a string that contains sourceMappingURL the step over/ step into fails and the debugger hits the next break point (like continue)
**To Reproduce**
Steps to reproduce the behavior:

1. compile any js file with babel using source maps flag
2. In another JS file make an eval call by using the contents of the compiled file as a string.
3. Create a launch configuration in VSCode with pauseForSourceMap as true
4. Add a break point  before the eval call 
5. Try to step over or step into this step would fail

**Log File**


[vscode-debugadapter-1af15ec5.json.gz](https://github.com/microsoft/vscode-js-debug/files/10691077/vscode-debugadapter-1af15ec5.json.gz)


**VS Code Version:**  
Version: 1.74.3

**Additional context**
Add any other context about the problem here.

https://user-images.githubusercontent.com/105740053/217680244-95b6ae47-7d0e-4988-9297-7153812d9d8a.mov





Discussion: The `sourceURL` you provide is not a fully qualified URL (or an absolute file path, which we also accept since naughty tooling sometimes generates those). Thus, we don't know "where" the script is and cannot load sources in its sourcemap, and stepping into it is skipped via [smart stepping](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_smart-stepping).

Providing a fully qualified URI or absolute path in the sourceURL comment will resolve the issue.
Hi Connor, thanks for the quick reply. Whether the source map is valid or invalid, I expect if I step over the eval code I should pause on line 9. Currently with pauseForSourceMap and also runtimeSourcemapPausePatterns config, it executes the rest of the program and pauses at the next breakpoint. (This happens regardless of the smartStep option).
Will be fixed in the [next nightly](https://github.com/microsoft/vscode-js-debug#nightly-extension)



Fix (patch):
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 605a12030..44bd6df66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This changelog records changes to stable releases since 1.50.2. "TBA" changes he
 - fix: recursive source map resolution parsing ignored locations ([vscode#169733](https://github.com/microsoft/vscode/issues/169733))
 - fix: unbound breakpoints in sourcemaps on Chrome 112 ([#1567](https://github.com/microsoft/vscode-js-debug/issues/1567))
 - fix: assorted bad source behaviors when reloading a page ([#1582](https://github.com/microsoft/vscode-js-debug/issues/1582))
+- fix: step over eval/new Function with sourcemaps not working ([#1556](https://github.com/microsoft/vscode-js-debug/issues/1556))
 - chore: remove webpack, adopt esbuild
 
 ## v1.76 (February 2023)
diff --git a/src/adapter/debugAdapter.ts b/src/adapter/debugAdapter.ts
index 0fd26dd2d..927acb5dc 100644
--- a/src/adapter/debugAdapter.ts
+++ b/src/adapter/debugAdapter.ts
@@ -9,7 +9,7 @@ import { DisposableList, IDisposable } from '../common/disposable';
 import { ILogger, LogTag } from '../common/logging';
 import { posInt32Counter, truthy } from '../common/objUtils';
 import { Base1Position } from '../common/positions';
-import { getDeferred, IDeferred } from '../common/promiseUtil';
+import { IDeferred, getDeferred } from '../common/promiseUtil';
 import { IRenameProvider } from '../common/sourceMaps/renameProvider';
 import * as sourceUtils from '../common/sourceUtils';
 import * as urlUtils from '../common/urlUtils';
@@ -17,7 +17,7 @@ import { AnyLaunchConfiguration } from '../configuration';
 import Dap from '../dap/api';
 import * as errors from '../dap/errors';
 import { ProtocolError } from '../dap/protocolError';
-import { disposeContainer, FS, FsPromises } from '../ioc-extras';
+import { FS, FsPromises, disposeContainer } from '../ioc-extras';
 import { ITarget } from '../targets/targets';
 import { ITelemetryReporter } from '../telemetry/telemetryReporter';
 import { IShutdownParticipants } from '../ui/shutdownParticipants';
@@ -392,13 +392,20 @@ export class DebugAdapter implements IDisposable {
       throw new ProtocolError(errors.threadNotAvailable());
     }
 
-    const { result, ...rest } = await this._thread.evaluate({
+    const r = await this._thread.evaluate({
       expression: `${params.expression} = ${sourceUtils.wrapObjectLiteral(params.value)}`,
       context: 'repl',
       frameId: params.frameId,
     });
 
-    return { value: result, ...rest };
+    return {
+      value: r.result,
+      variablesReference: r.variablesReference,
+      indexedVariables: r.indexedVariables,
+      namedVariables: r.namedVariables,
+      presentationHint: r.presentationHint,
+      type: r.type,
+    };
   }
 
   async _onSetVariable(params: Dap.SetVariableParams): Promise<Dap.SetVariableResult | Dap.Error> {
diff --git a/src/adapter/threads.ts b/src/adapter/threads.ts
index 7fa4f9c6c..ced5a99f3 100644
--- a/src/adapter/threads.ts
+++ b/src/adapter/threads.ts
@@ -853,6 +853,14 @@ export class Thread implements IVariableStoreLocationProvider {
         )
       ) {
         // Check if there are any user-defined breakpoints on this line
+      } else if (
+        this._expectedPauseReason?.reason === 'step' &&
+        this._expectedPauseReason.direction === StepDirection.Over
+      ) {
+        // Check if we're in the middle of a step over, e.g. stepping over a
+        // function compilation. Stepping in should still remain paused,
+        // and an instrumentation pause in step out should not be possible.
+        return this._cdp.Debugger.stepOut({});
       } else {
         // If none of this above, it's pure instrumentation.
         return this.resume();
diff --git a/src/targets/node/nodeTarget.ts b/src/targets/node/nodeTarget.ts
index 26d75c887..fb9769b43 100644
--- a/src/targets/node/nodeTarget.ts
+++ b/src/targets/node/nodeTarget.ts
@@ -151,8 +151,10 @@ export class NodeTarget implements ITarget {
     this._cdp.NodeWorker.enable({ waitForDebuggerOnStart: true });
 
     if (result && '__dynamicAttach' in result) {
-      await this._cdp.Debugger.enable({});
+      // order matters! The runtime must be enabled first so we know what
+      // execution contexts scripts are in
       await this._cdp.Runtime.enable({});
+      await this._cdp.Debugger.enable({});
     }
 
     let defaultCountextId: number;