Skip to content

Patch for multi disk support on Windows(TS Sourcemap) #493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ node_modules/
out/
.vscode-test/
coverage/
.idea

# Sample Application auto-generated files
SampleApplication/.vscode/.react/debuggerWorker.js
Expand Down
31 changes: 25 additions & 6 deletions src/debugger/sourceMapsCombinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as path from "path";
import { SourceMapConsumer, RawSourceMap, SourceMapGenerator, MappingItem, Mapping, Position, MappedPosition } from "source-map";
import sourceMapResolve = require("source-map-resolve");

const DISK: RegExp = /^[a-z]:/i;
Copy link
Contributor

Choose a reason for hiding this comment

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

DISK -> DISK_LETTER_RE


export class SourceMapsCombinator {

public convert(rawBundleSourcemap: RawSourceMap): RawSourceMap {
Expand Down Expand Up @@ -59,11 +61,13 @@ export class SourceMapsCombinator {

// Resolve TS source path to absolute because it might be relative to generated JS
// (this depends on whether "sourceRoot" option is specified in tsconfig.json)
tsPosition.source = path.resolve(
rawBundleSourcemap.sourceRoot,
path.dirname(item.source),
tsPosition.source
);
if (!tsPosition.source.match(DISK)) {
tsPosition.source = path.resolve(
rawBundleSourcemap.sourceRoot,
path.dirname(item.source),
tsPosition.source
);
}

// Update mapping w/ mapped position values
mapping = {
Expand All @@ -90,10 +94,25 @@ export class SourceMapsCombinator {
}

private readSourcemap(file: string, code: string): SourceMapConsumer | null {
let result = sourceMapResolve.resolveSync(code, file, fs.readFileSync);
let result = sourceMapResolve.resolveSync(code, file, readFileSync.bind(null, getDiskLetter(file)));
if (result === null) {
return null;
}
return new SourceMapConsumer(result.map);
}
}

// Hack for source-map-resolve and cutted disk letter
// https://github.com/lydell/source-map-resolve/issues/9
function readFileSync(diskLetter: string, filePath: string) {
if (filePath.match(DISK)) {
return fs.readFileSync(filePath);
} else {
return fs.readFileSync(`${diskLetter}${filePath}`);
}
}

function getDiskLetter(filePath: string): string {
const matched = filePath.match(DISK);
return matched ? matched[0] : "";
}
13 changes: 13 additions & 0 deletions src/test/debugger/assets/hello.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
class Hello {
constructor (public msg: string) {
}
public sayHello() {
return this.msg;
}
}

const hello = new Hello("HelloWorld!");

console.log(hello.sayHello());
55 changes: 55 additions & 0 deletions src/test/debugger/sourceMapsCombinator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

import { SourceMapsCombinator } from "../../debugger/sourceMapsCombinator";

import * as assert from "assert";
import * as sinon from "sinon";
import * as fs from "fs";
import * as path from "path";

suite("sourceMapsCombinator", function () {
let sandbox: Sinon.SinonSandbox;

setup(() => {
sandbox = sinon.sandbox.create();
});

suiteTeardown(() => {
sandbox.restore();
});

suite("#convert", function () {
test("convert sourcemap", function () {
const pathToJS = "d:/hello.js";
const pathToTS = "d:/hello.ts";
const sourcemapPath = "d:/hello.js.map";
const code = fs.readFileSync(path.resolve(__dirname, "assets/hello.js"));
const mapTS = `{"version":3,"sources":["d:/hello.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM;IACR,YAAY,CAAC,OAAO,GAAG,EAAE,MAAM,CAAC;IAChC;IACA,OAAO,QAAQ,CAAC,EAAE;QACd,OAAO,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO;IACtC;AACJ;;AAEA,MAAM,MAAM,EAAE,IAAI,KAAK,CAAC,gDAAgD,CAAC;;AAEzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC","file":"hello.js","sourceRoot":""}`;
const codeTS = fs.readFileSync(path.resolve(__dirname, "../../../src/test/debugger/assets/hello.ts"));

const expected = {
"version": 3,
"sources": [
"d:/hello.ts",
],
"names": [],
"mappings": "AAAA,IAAA,MAAM,EAAM,CAAA,SAAA,CAAA,EAAA;IACR,SAAA,KAAa,CAAA,GAAA,EAAO;QACpB,IAAA,CAAA,IAAA,EAAA,GAAA;IACA;SACI,CAAA,SAAO,CAAA,SAAc,EAAA,SAAM,CAAA,EAAO;QACtC,OAAA,OAAA,EAAA,IAAA,CAAA,IAAA,EAAA,OAAA;IACJ,CAAA;;AAEA,CAAA,CAAA,CAAA,CAAA;;AAEA,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC",
};

let rawBundleSourcemap = { "version": 3, "sources": ["d:/hello.js"], "names": [], "mappings": "AAAA,IAAI,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;IACrB,SAAS,KAAK,CAAC,GAAG,EAAE;QAChB,IAAI,CAAC,IAAI,EAAE,GAAG;IAClB;IACA,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE;QACnC,OAAO,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO;IACtC,CAAC;IACD,OAAO,KAAK;AAChB,CAAC,CAAC,CAAC,CAAC;AACJ,IAAI,MAAM,EAAE,IAAI,KAAK,CAAC,gDAAgD,CAAC;AACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC", "file": "hello.js", "sourceRoot": "" };

const stub = sandbox.stub(fs, "readFileSync");

stub.withArgs(pathToJS).returns(code);
Copy link
Contributor

Choose a reason for hiding this comment

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

Pls rename stub -> fsReadFileStub

stub.withArgs(sourcemapPath).returns(mapTS);
stub.withArgs(pathToTS).returns(codeTS);
let sourceMapsCombinator = new SourceMapsCombinator();
let result = sourceMapsCombinator.convert(rawBundleSourcemap);
result.sources = result.sources.map(p => {
return p.replace(/\\/g, "/");
});
assert.deepEqual(expected, result);
});
});
});