From 4ad48c30bc931e83b43c816ccf21ffd015fda77d Mon Sep 17 00:00:00 2001 From: Soo Jae Hwang Date: Tue, 14 Nov 2017 14:23:46 +0900 Subject: [PATCH 1/2] Add test to verify error object after transform not showing correct location --- .../_config.js | 39 +++++++++++++++++++ .../empty.js | 0 .../main.js | 3 ++ 3 files changed, 42 insertions(+) create mode 100644 test/function/samples/error-after-transform-should-throw-correct-location/_config.js create mode 100644 test/function/samples/error-after-transform-should-throw-correct-location/empty.js create mode 100644 test/function/samples/error-after-transform-should-throw-correct-location/main.js diff --git a/test/function/samples/error-after-transform-should-throw-correct-location/_config.js b/test/function/samples/error-after-transform-should-throw-correct-location/_config.js new file mode 100644 index 00000000000..613fe35e570 --- /dev/null +++ b/test/function/samples/error-after-transform-should-throw-correct-location/_config.js @@ -0,0 +1,39 @@ +var path = require( 'path' ); +var assert = require( 'assert' ); +var MagicString = require( 'magic-string' ); + +module.exports = { + description: 'error after transform should throw with correct location of file', + options: { + plugins: [ + { + transform: function ( source, id ) { + var s = new MagicString( source ); + s.prepend( "import _assign from 'object-assign';\n" ); + + return { + code: s.toString(), + map: s.generateMap({ hires: true }) + }; + } + } + ] + }, + error: { + code: 'MISSING_EXPORT', + message: `'default' is not exported by empty.js`, + pos: 44, + loc: { + file: path.resolve( __dirname, 'main.js' ), + line: 1, + column: 7 + }, + frame: ` + 1: import a from './empty.js'; + ^ + 2: + 3: Object.assign({}, a); + `, + url: `https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module` + } +}; diff --git a/test/function/samples/error-after-transform-should-throw-correct-location/empty.js b/test/function/samples/error-after-transform-should-throw-correct-location/empty.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/function/samples/error-after-transform-should-throw-correct-location/main.js b/test/function/samples/error-after-transform-should-throw-correct-location/main.js new file mode 100644 index 00000000000..860653acef7 --- /dev/null +++ b/test/function/samples/error-after-transform-should-throw-correct-location/main.js @@ -0,0 +1,3 @@ +import a from './empty.js'; + +Object.assign({}, a); From bb7411aa87916fe25af9e7cf207d6e02605a2c38 Mon Sep 17 00:00:00 2001 From: Soo Jae Hwang Date: Tue, 14 Nov 2017 14:24:54 +0900 Subject: [PATCH 2/2] Add getOriginalLocation method into Module.js to return correct error location --- src/Module.js | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Module.js b/src/Module.js index bf67e9520e2..3809d3e095c 100644 --- a/src/Module.js +++ b/src/Module.js @@ -14,6 +14,8 @@ import extractNames from './ast/utils/extractNames.js'; import enhance from './ast/enhance.js'; import clone from './ast/clone.js'; import ModuleScope from './ast/scopes/ModuleScope.js'; +import { encode } from 'sourcemap-codec'; +import { SourceMapConsumer } from 'source-map'; function tryParse ( module, acornOptions ) { try { @@ -282,14 +284,40 @@ export default class Module { } } + getOriginalLocation (sourcemapChain, line, column) { + let location = { + line, + column + }; + const filteredSourcemapChain = + sourcemapChain.filter(sourcemap => sourcemap.mappings).map(sourcemap => { + const encodedSourcemap = sourcemap; + if (sourcemap.mappings) { + encodedSourcemap.mappings = encode(encodedSourcemap.mappings); + } + return encodedSourcemap; + }); + while (filteredSourcemapChain.length > 0) { + const sourcemap = filteredSourcemapChain.pop(); + const smc = new SourceMapConsumer(sourcemap); + location = smc.originalPositionFor({ + line: location.line, + column: location.column + }); + } + return location; + } + error ( props, pos ) { if ( pos !== undefined ) { props.pos = pos; const { line, column } = locate( this.code, pos, { offsetLine: 1 } ); // TODO trace sourcemaps - props.loc = { file: this.id, line, column }; - props.frame = getCodeFrame( this.code, line, column ); + const location = this.getOriginalLocation(this.sourcemapChain, line, column); + + props.loc = { file: this.id, line: location.line, column: location.column }; + props.frame = getCodeFrame( this.originalCode, location.line, location.column ); } error( props );