Skip to content

SWC generates incorrect source maps when typescript inputSourceMap is provided #10504

@tough-griff

Description

@tough-griff

Describe the bug

When handling code that has already been transformed by tsc with a generated source map swc will generate an incorrect source map that points to the incorrect locations in the original file.

Input code

src/typescript.ts

interface MyObject {
  [key: string]: any;
}

let foo = 'foo';
let boo = 'boo';
let bar = 'bar';
let baz = 'baz';

foo += bar;

eval("function hi(name) { return `Hi ${name}` } hi('world!')");

const key: string = 'key';
const obj: MyObject = Object.create(null)
const dynamic = 'somedynamickey';

switch (key) {
  case obj[dynamic]:
  case dynamic:
  case 'literal':
}

const abc = boo + baz;
const def = boo == baz;
const ghi = boo === baz;
const jkl = boo != baz;
const mno = boo !== baz;

const word = 'world';
const str = `hello ${word}`;

tsconfig.json

{
  "extends": "@tsconfig/node16/tsconfig.json",
  "compilerOptions": {
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
  },
  "include": [
    "src/**/*.ts"
  ],
}

dist/typescript.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
let foo = 'foo';
let boo = 'boo';
let bar = 'bar';
let baz = 'baz';
foo += bar;
eval("function hi(name) { return `Hi ${name}` } hi('world!')");
const key = 'key';
const obj = Object.create(null);
const dynamic = 'somedynamickey';
switch (key) {
    case obj[dynamic]:
    case dynamic:
    case 'literal':
}
const abc = boo + baz;
const def = boo == baz;
const ghi = boo === baz;
const jkl = boo != baz;
const mno = boo !== baz;
const word = 'world';
const str = `hello ${word}`;
//# sourceMappingURL=typescript.js.map

dist/typescript.js.map

{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../src/typescript.ts"],"names":[],"mappings":";;AAIA,IAAI,GAAG,GAAG,KAAK,CAAC;AAChB,IAAI,GAAG,GAAG,KAAK,CAAC;AAChB,IAAI,GAAG,GAAG,KAAK,CAAC;AAChB,IAAI,GAAG,GAAG,KAAK,CAAC;AAEhB,GAAG,IAAI,GAAG,CAAC;AAEX,IAAI,CAAC,wDAAwD,CAAC,CAAC;AAE/D,MAAM,GAAG,GAAW,KAAK,CAAC;AAC1B,MAAM,GAAG,GAAa,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AACzC,MAAM,OAAO,GAAG,gBAAgB,CAAC;AAEjC,QAAQ,GAAG,EAAE,CAAC;IACZ,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;IAClB,KAAK,OAAO,CAAC;IACb,KAAK,SAAS,CAAC;AACjB,CAAC;AAED,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACtB,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC;AACvB,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC;AACxB,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC;AACvB,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC;AAExB,MAAM,IAAI,GAAG,OAAO,CAAC;AACrB,MAAM,GAAG,GAAG,SAAS,IAAI,EAAE,CAAC"}

Config

{
  "env": {
    "targets": {
      "node": "20",
    },
  },
  "jsc": { "minify": { "compress": { "defaults": false } } },
  "minify": true,
  "sourceMaps": true
}

Link to the code that reproduces this issue

https://gist.github.com/tough-griff/e300d5d8020d59b8d89ad94cf56175c3

SWC Info output

Operating System:
    Platform: darwin
    Arch: arm64
    Machine Type: arm64
    Version: Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:49 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6000
    CPU: (10 cores)
        Models: Apple M1 Max

Binaries:
    Node: 20.19.0
    npm: 10.8.2
    Yarn: N/A
    pnpm: N/A

Relevant Packages:
    @swc/core: 1.11.24
    @swc/helpers: N/A
    @swc/types: 0.1.21
    typescript: 5.8.3

SWC Config:
    output: N/A
    .swcrc path: N/A

Next.js info:
    output: N/A

Expected behavior

Image

Actual behavior

While the source code is not visible, you can still see the error: the generated source map does not seem to handle the newlines in the typescript source correctly and puts the first span from a newline on the previous code line:

Image

This leads to further errors when implementing a transform plugin that replaces operators with functions. The source map for the generated code points to the incorrect line previous line.

Version

@swc/core: 1.11.24

Additional context

typescript example
See: https://evanw.github.io/source-map-visualization/#NDc0ACJ1c2Ugc3RyaWN0IjtPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywiX19lc01vZHVsZSIse3ZhbHVlOnRydWV9KTtsZXQgZm9vPSJmb28iO2xldCBib289ImJvbyI7bGV0IGJhcj0iYmFyIjtsZXQgYmF6PSJiYXoiO2Zvbys9YmFyO2V2YWwoImZ1bmN0aW9uIGhpKG5hbWUpIHsgcmV0dXJuIGBIaSAke25hbWV9YCB9IGhpKCd3b3JsZCEnKSIpO2NvbnN0IGtleT0ia2V5Ijtjb25zdCBvYmo9T2JqZWN0LmNyZWF0ZShudWxsKTtjb25zdCBkeW5hbWljPSJzb21lZHluYW1pY2tleSI7c3dpdGNoKGtleSl7Y2FzZSBvYmpbZHluYW1pY106Y2FzZSBkeW5hbWljOmNhc2UibGl0ZXJhbCI6fWNvbnN0IGFiYz1ib28rYmF6O2NvbnN0IGRlZj1ib289PWJhejtjb25zdCBnaGk9Ym9vPT09YmF6O2NvbnN0IGprbD1ib28hPWJhejtjb25zdCBtbm89Ym9vIT09YmF6O2NvbnN0IHdvcmQ9IndvcmxkIjtjb25zdCBzdHI9YGhlbGxvICR7d29yZH1gOzgyMwB7InZlcnNpb24iOjMsImZpbGUiOiJ0eXBlc2NyaXB0LmpzIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXNjcmlwdC50cyJdLCJzb3VyY2VSb290IjoiIiwibmFtZXMiOltdLCJtYXBwaW5ncyI6InNFQUlBLElBQUksR0FBRyxDQUFHLEtBQUssQ0FBQyxBQUNoQixJQUFJLEdBQUcsQ0FBRyxLQUFLLENBQUMsQUFDaEIsSUFBSSxHQUFHLENBQUcsS0FBSyxDQUFDLEFBQ2hCLElBQUksR0FBRyxDQUFHLEtBQUssQ0FBQyxBQUVoQixHQUFHLEVBQUksR0FBRyxDQUFDLEFBRVgsSUFBSSxDQUFDLHdEQUF3RCxDQUFDLENBQUMsQUFFL0QsTUFBTSxHQUFHLENBQVcsS0FBSyxDQUN6QixBQUQwQixNQUNwQixHQUFHLENBQWEsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQSxBQUN6QyxNQUFNLE9BQU8sQ0FBRyxnQkFBZ0IsQ0FFaEMsQUFGaUMsT0FFekIsR0FBRyxFQUFFLEFBQ1gsQ0FEWSxJQUNQLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxBQUNsQixLQUFLLE9BQU8sQ0FBQyxBQUNiLElBQUssU0FBUyxDQUNoQixBQURpQixDQUNoQixBQUVELE1BQU0sR0FBRyxDQUFHLEdBQUcsQ0FBRyxHQUFHLENBQUMsQUFDdEIsTUFBTSxHQUFHLENBQUcsR0FBRyxFQUFJLEdBQUcsQ0FBQyxBQUN2QixNQUFNLEdBQUcsQ0FBRyxHQUFHLEdBQUssR0FBRyxDQUFDLEFBQ3hCLE1BQU0sR0FBRyxDQUFHLEdBQUcsRUFBSSxHQUFHLENBQUMsQUFDdkIsTUFBTSxHQUFHLENBQUcsR0FBRyxHQUFLLEdBQUcsQ0FBQyxBQUV4QixNQUFNLElBQUksQ0FBRyxPQUFPLENBQUMsQUFDckIsTUFBTSxHQUFHLENBQUcsQ0FBQSxNQUFBLEVBQVMsSUFBSSxDQUFBLENBQUUsQ0FBQyJ9

javascript example
https://evanw.github.io/source-map-visualization/#NDE3ACJ1c2Ugc3RyaWN0IjtsZXQgZm9vPSJmb28iO2xldCBib289ImJvbyI7bGV0IGJhcj0iYmFyIjtsZXQgYmF6PSJiYXoiO2Zvbys9YmFyO2V2YWwoImZ1bmN0aW9uIGhpKG5hbWUpIHsgcmV0dXJuIGBIaSAke25hbWV9YCB9IGhpKCd3b3JsZCEnKSIpO2NvbnN0IGtleT0ia2V5Ijtjb25zdCBvYmo9T2JqZWN0LmNyZWF0ZShudWxsKTtjb25zdCBkeW5hbWljPSJzb21lZHluYW1pY2tleSI7c3dpdGNoKGtleSl7Y2FzZSBvYmpbZHluYW1pY106Y2FzZSBkeW5hbWljOmNhc2UibGl0ZXJhbCI6fWNvbnN0IGFiYz1ib28rYmF6O2NvbnN0IGRlZj1ib289PWJhejtjb25zdCBnaGk9Ym9vPT09YmF6O2NvbnN0IGprbD1ib28hPWJhejtjb25zdCBtbm89Ym9vIT09YmF6O2NvbnN0IHdvcmQ9IndvcmxkIjtjb25zdCBzdHI9YGhlbGxvICR7d29yZH1gOzExODgAeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9ncmlmZmluL0NvbnRyYXN0L25vZGUtc3djLXBsdWdpbnMvdGVzdC9zd2MtYnVnL3NyYy9qYXZhc2NyaXB0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxubGV0IGZvbyA9ICdmb28nO1xubGV0IGJvbyA9ICdib28nO1xubGV0IGJhciA9ICdiYXInO1xubGV0IGJheiA9ICdiYXonO1xuXG5mb28gKz0gYmFyO1xuXG5ldmFsKFwiZnVuY3Rpb24gaGkobmFtZSkgeyByZXR1cm4gYEhpICR7bmFtZX1gIH0gaGkoJ3dvcmxkIScpXCIpO1xuXG5jb25zdCBrZXkgPSAna2V5JztcbmNvbnN0IG9iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5jb25zdCBkeW5hbWljID0gJ3NvbWVkeW5hbWlja2V5Jztcblxuc3dpdGNoIChrZXkpIHtcbiAgY2FzZSBvYmpbZHluYW1pY106XG4gIGNhc2UgZHluYW1pYzpcbiAgY2FzZSAnbGl0ZXJhbCc6XG59XG5cbmNvbnN0IGFiYyA9IGJvbyArIGJhejtcbmNvbnN0IGRlZiA9IGJvbyA9PSBiYXo7XG5jb25zdCBnaGkgPSBib28gPT09IGJhejtcbmNvbnN0IGprbCA9IGJvbyAhPSBiYXo7XG5jb25zdCBtbm8gPSBib28gIT09IGJhejtcblxuY29uc3Qgd29yZCA9ICd3b3JsZCc7XG5jb25zdCBzdHIgPSBgaGVsbG8gJHt3b3JkfWA7XG4iXSwibmFtZXMiOlsiZm9vIiwiYm9vIiwiYmFyIiwiYmF6IiwiZXZhbCIsImtleSIsIm9iaiIsIk9iamVjdCIsImNyZWF0ZSIsImR5bmFtaWMiLCJhYmMiLCJkZWYiLCJnaGkiLCJqa2wiLCJtbm8iLCJ3b3JkIiwic3RyIl0sIm1hcHBpbmdzIjoiQUFBQSxhQUVBLElBQUlBLElBQU0sTUFDVixJQUFJQyxJQUFNLE1BQ1YsSUFBSUMsSUFBTSxNQUNWLElBQUlDLElBQU0sTUFFVkgsS0FBT0UsSUFFUEUsS0FBSywwREFFTCxNQUFNQyxJQUFNLE1BQ1osTUFBTUMsSUFBTUMsT0FBT0MsTUFBTSxDQUFDLE1BQzFCLE1BQU1DLFFBQVUsaUJBRWhCLE9BQVFKLEtBQ04sS0FBS0MsR0FBRyxDQUFDRyxRQUFRLENBQ2pCLEtBQUtBLFFBQ0wsSUFBSyxVQUNQLENBRUEsTUFBTUMsSUFBTVQsSUFBTUUsSUFDbEIsTUFBTVEsSUFBTVYsS0FBT0UsSUFDbkIsTUFBTVMsSUFBTVgsTUFBUUUsSUFDcEIsTUFBTVUsSUFBTVosS0FBT0UsSUFDbkIsTUFBTVcsSUFBTWIsTUFBUUUsSUFFcEIsTUFBTVksS0FBTyxRQUNiLE1BQU1DLElBQU0sQ0FBQyxNQUFNLEVBQUVELEtBQUssQ0FBQyJ9

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions