diff --git a/src/transformers/baseSourceMapTransformer.ts b/src/transformers/baseSourceMapTransformer.ts index e9d30b7ec..084f11a33 100644 --- a/src/transformers/baseSourceMapTransformer.ts +++ b/src/transformers/baseSourceMapTransformer.ts @@ -14,6 +14,7 @@ import { logger } from 'vscode-debugadapter'; import * as nls from 'vscode-nls'; import { ScriptContainer } from '../chrome/scripts'; +import { isInternalRemotePath } from '../remoteMapper'; const localize = nls.loadMessageBundle(); interface ISavedSetBreakpointsArgs { @@ -231,31 +232,34 @@ export class BaseSourceMapTransformer { await this._processingNewSourceMap; const mapped = this._sourceMaps.mapToAuthored(sourceLocation.source.path, sourceLocation.line, sourceLocation.column); - if (mapped && utils.existsSync(mapped.source)) { - // Script was mapped to a valid path + if (mapped && (isInternalRemotePath(mapped.source) || utils.existsSync(mapped.source))) { + // Script was mapped to a valid local path or internal path sourceLocation.source.path = mapped.source; sourceLocation.source.sourceReference = undefined; sourceLocation.source.name = path.basename(mapped.source); sourceLocation.line = mapped.line; sourceLocation.column = mapped.column; sourceLocation.isSourceMapped = true; - } else { - const inlinedSource = mapped && this._sourceMaps.sourceContentFor(mapped.source); - if (mapped && inlinedSource) { - // Clear the path and set the sourceReference - the client will ask for - // the source later and it will be returned from the sourcemap - sourceLocation.source.name = path.basename(mapped.source); - sourceLocation.source.path = mapped.source; - sourceLocation.source.sourceReference = this._scriptContainer.getSourceReferenceForScriptPath(mapped.source, inlinedSource); - sourceLocation.source.origin = localize('origin.inlined.source.map', 'read-only inlined content from source map'); - sourceLocation.line = mapped.line; - sourceLocation.column = mapped.column; - sourceLocation.isSourceMapped = true; - } else if (utils.existsSync(sourceLocation.source.path)) { - // Script could not be mapped, but does exist on disk. Keep it and clear the sourceReference. - sourceLocation.source.sourceReference = undefined; - sourceLocation.source.origin = undefined; - } + return; + } + const inlinedSource = mapped && this._sourceMaps.sourceContentFor(mapped.source); + if (mapped && inlinedSource) { + // Clear the path and set the sourceReference - the client will ask for + // the source later and it will be returned from the sourcemap + sourceLocation.source.name = path.basename(mapped.source); + sourceLocation.source.path = mapped.source; + sourceLocation.source.sourceReference = this._scriptContainer.getSourceReferenceForScriptPath(mapped.source, inlinedSource); + sourceLocation.source.origin = localize('origin.inlined.source.map', 'read-only inlined content from source map'); + sourceLocation.line = mapped.line; + sourceLocation.column = mapped.column; + sourceLocation.isSourceMapped = true; + return; + } + if (utils.existsSync(sourceLocation.source.path)) { + // Script could not be mapped, but does exist on disk. Keep it and clear the sourceReference. + sourceLocation.source.sourceReference = undefined; + sourceLocation.source.origin = undefined; + return; } } diff --git a/test/transformers/baseSourceMapTransformer.test.ts b/test/transformers/baseSourceMapTransformer.test.ts index d2342e5ff..05701e915 100644 --- a/test/transformers/baseSourceMapTransformer.test.ts +++ b/test/transformers/baseSourceMapTransformer.test.ts @@ -15,6 +15,7 @@ import * as testUtils from '../testUtils'; import { SourceMaps } from '../../src/sourceMaps/sourceMaps'; import { MappedPosition } from '../../src/sourceMaps/sourceMap'; import * as utils from '../../src/utils'; +import * as remoteMapper from '../../src/remoteMapper'; /* tslint:disable:no-function-expression */ @@ -51,6 +52,7 @@ import {BaseSourceMapTransformer as _BaseSourceMapTransformer } from '../../src/ suite('BaseSourceMapTransformer', () => { let utilsMock: IMock; + let remoteMapperMock: IMock; setup(() => { testUtils.setupUnhandledRejectionListener(); @@ -60,6 +62,10 @@ suite('BaseSourceMapTransformer', () => { utilsMock.callBase = true; mockery.registerMock('../utils', utilsMock.object); + remoteMapperMock = Mock.ofInstance(remoteMapper); + remoteMapperMock.callBase = true; + mockery.registerMock('../remoteMapper', remoteMapperMock.object); + // Set up mockery mockery.enable({ warnOnReplace: false, useCleanCache: true, warnOnUnregistered: false }); }); @@ -269,6 +275,21 @@ suite('BaseSourceMapTransformer', () => { assert.deepEqual(response, expected); }); + test(`apply to mapped source when using internal remote url`, async () => { + utilsMock + .setup(x => x.existsSync(It.isValue(AUTHORED_PATH))) + .returns(() => false); + remoteMapperMock + .setup(x => x.isInternalRemotePath(It.isValue(AUTHORED_PATH))) + .returns(() => true); + + const response = testUtils.getStackTraceResponseBody(RUNTIME_PATH, RUNTIME_BPS(), [1, 2, 3]); + const expected = testUtils.getStackTraceResponseBody(AUTHORED_PATH, AUTHORED_BPS(), undefined, /*isSourceMapped=*/true); + + await getTransformer().stackTraceResponse(response); + assert.deepEqual(response, expected); + }); + test('doesn\'t clear the path when there are no sourcemaps', async () => { const response = testUtils.getStackTraceResponseBody(RUNTIME_PATH, RUNTIME_BPS(), [1, 2, 3]);