diff --git a/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/.parcelrc b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/.parcelrc new file mode 100644 index 00000000000..becb72f7850 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/.parcelrc @@ -0,0 +1,6 @@ +{ + "extends": "@parcel/config-default", + "transformers": { + "*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"] + } +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/index.ts b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/index.ts new file mode 100644 index 00000000000..4bddce60aed --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/index.ts @@ -0,0 +1,5 @@ +// comment + +type X = number; + +nonExistsFunc(); diff --git a/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/package.json b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/package.json new file mode 100644 index 00000000000..20b7871d386 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/package.json @@ -0,0 +1,6 @@ +{ + "name": "parcel-sourcemap-integration-test", + "version": "1.0.0", + "license": "MIT", + "private": true +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/yarn.lock b/packages/core/integration-tests/test/integration/sourcemap-typescript-tsc/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/sourcemaps.js b/packages/core/integration-tests/test/sourcemaps.js index 1879beb6207..e35e4f7272e 100644 --- a/packages/core/integration-tests/test/sourcemaps.js +++ b/packages/core/integration-tests/test/sourcemaps.js @@ -563,6 +563,46 @@ describe('sourcemaps', function () { }); }); + it('should create a valid sourcemap when using the Typescript tsc transformer', async function () { + let inputFilePath = path.join( + __dirname, + '/integration/sourcemap-typescript-tsc/index.ts', + ); + + await bundle(inputFilePath); + let distDir = path.join(__dirname, '../dist/'); + let filename = path.join(distDir, 'index.js'); + let raw = await outputFS.readFile(filename, 'utf8'); + let mapUrlData = await loadSourceMapUrl(outputFS, filename, raw); + if (!mapUrlData) { + throw new Error('Could not load map'); + } + let map = mapUrlData.map; + + assert.equal(map.file, 'index.js.map'); + assert(raw.includes('//# sourceMappingURL=index.js.map')); + // assert.equal(map.sourceRoot, '/__parcel_source_root/'); + + let sourceMap = new SourceMap('/'); + sourceMap.addVLQMap(map); + + let mapData = sourceMap.getMap(); + assert.equal(mapData.sources.length, 1); + assert.deepEqual(mapData.sources, ['index.ts']); + + let input = await inputFS.readFile( + path.join(path.dirname(filename), map.sourceRoot, map.sources[0]), + 'utf8', + ); + checkSourceMapping({ + map: sourceMap, + source: input, + generated: raw, + str: 'nonExistsFunc', + sourcePath: 'index.ts', + }); + }); + it('should create a valid sourcemap for a CSS bundle', async function () { async function test(minify) { let inputFilePath = path.join( diff --git a/packages/transformers/typescript-tsc/package.json b/packages/transformers/typescript-tsc/package.json index 6e8a307888c..0cadc107fe5 100644 --- a/packages/transformers/typescript-tsc/package.json +++ b/packages/transformers/typescript-tsc/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@parcel/plugin": "^2.0.1", + "@parcel/source-map": "^2.0.0", "@parcel/ts-utils": "^2.0.1" }, "devDependencies": { diff --git a/packages/transformers/typescript-tsc/src/TSCTransformer.js b/packages/transformers/typescript-tsc/src/TSCTransformer.js index a32102c487b..ae44f5d126a 100644 --- a/packages/transformers/typescript-tsc/src/TSCTransformer.js +++ b/packages/transformers/typescript-tsc/src/TSCTransformer.js @@ -5,13 +5,14 @@ import type {TranspileOptions} from 'typescript'; import {Transformer} from '@parcel/plugin'; import {loadTSConfig} from '@parcel/ts-utils'; import typescript from 'typescript'; +import SourceMap from '@parcel/source-map'; export default (new Transformer({ loadConfig({config, options}) { return loadTSConfig(config, options); }, - async transform({asset, config}) { + async transform({asset, config, options}) { asset.type = 'js'; let code = await asset.getCode(); @@ -29,15 +30,29 @@ export default (new Transformer({ // Don't compile ES `import`s -- scope hoisting prefers them and they will // otherwise compiled to CJS via babel in the js transformer module: typescript.ModuleKind.ESNext, + sourceMap: !!asset.env.sourceMap, }, fileName: asset.filePath, // Should be relativePath? }: TranspileOptions), ); + let map; + let {outputText, sourceMapText} = transpiled; + if (sourceMapText != null) { + map = new SourceMap(options.projectRoot); + map.addVLQMap(JSON.parse(sourceMapText)); + + outputText = outputText.substring( + 0, + outputText.lastIndexOf('//# sourceMappingURL'), + ); + } + return [ { type: 'js', - content: transpiled.outputText, + content: outputText, + map, }, ]; },