From 421a2af06462e486903a11bb0c5a74ff691f12ad Mon Sep 17 00:00:00 2001 From: log101 Date: Fri, 29 Mar 2024 23:38:53 +0300 Subject: [PATCH 1/3] fix: update error locations for processed modules --- lib/Compilation.js | 16 ++++- lib/util/sourceMap.js | 58 +++++++++++++++++++ package.json | 1 + .../StatsTestCases.basictest.js.snap | 7 +++ .../wrong-line-numbers-error/index.js | 3 + .../wrong-line-numbers-error/sampleLoader.js | 3 + .../webpack.config.js | 14 +++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 lib/util/sourceMap.js create mode 100644 test/statsCases/wrong-line-numbers-error/index.js create mode 100644 test/statsCases/wrong-line-numbers-error/sampleLoader.js create mode 100644 test/statsCases/wrong-line-numbers-error/webpack.config.js diff --git a/lib/Compilation.js b/lib/Compilation.js index 1526141bff6..3b9a96ebca3 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -82,6 +82,7 @@ const { const processAsyncTree = require("./util/processAsyncTree"); const { getRuntimeKey } = require("./util/runtime"); const { isSourceEqual } = require("./util/source"); +const updateErrorLocation = require("./util/sourceMap"); /** @template T @typedef {import("tapable").AsArray} AsArray */ /** @typedef {import("webpack-sources").Source} Source */ @@ -1850,8 +1851,19 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si this.warnings.push(err); return callback(); } else { - this.errors.push(err); - return callback(err); + // If module has a source map, update the error location using + // source map to avoid misaligned error location after loader processing + if (err.module && "useSourceMap" in err.module) { + if ("start" in err.loc) { + return updateErrorLocation(err, err => { + this.errors.push(err); + return callback(err); + }); + } + } else { + this.errors.push(err); + return callback(err); + } } } diff --git a/lib/util/sourceMap.js b/lib/util/sourceMap.js new file mode 100644 index 00000000000..0a516565c67 --- /dev/null +++ b/lib/util/sourceMap.js @@ -0,0 +1,58 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Furkan Erdem @log101 +*/ + +"use strict"; + +const { SourceMapConsumer } = require("source-map"); + +/** @typedef {import("../Compilation").ModuleCallback} ModuleCallback */ +/** @typedef {import("../Dependency").RealDependencyLocation} RealDependencyLocation */ +/** @typedef {import("../WebpackError")} WebpackError */ + +/** + * Updates error location (line number and column) using sourcemap + * + * @param {WebpackError} err The error with the misaligned location. + * @param {ModuleCallback} callback callback + * @returns {Promise} + */ +const updateErrorLocation = async (err, callback) => { + let consumer; + try { + consumer = await new SourceMapConsumer(err.module.originalSource().map()); + } catch (_err) { + return callback(err); + } + + // Have to check to avoid type error + if ("start" in err.loc) { + // find the original positions + const startLoc = consumer.originalPositionFor({ + line: err.loc.start.line, + column: err.loc.start.column + }); + + // update the error start location + err.loc.start.line = startLoc.line; + err.loc.start.column = startLoc.column; + } + + // end field is optional, check if exists + if ("end" in err.loc) { + // find the original positions + const endLoc = consumer.originalPositionFor({ + line: err.loc.end.line, + column: err.loc.end.column + }); + + // update the error end location + err.loc.end.line = endLoc.line; + err.loc.end.column = endLoc.column; + } + + return callback(err); +}; + +module.exports = updateErrorLocation; diff --git a/package.json b/package.json index 536892cb0d3..d4697ebb8d0 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", + "source-map": "^0.7.4", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.1", diff --git a/test/__snapshots__/StatsTestCases.basictest.js.snap b/test/__snapshots__/StatsTestCases.basictest.js.snap index 3909e7f9f0b..b2b7674a6b1 100644 --- a/test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/test/__snapshots__/StatsTestCases.basictest.js.snap @@ -4815,3 +4815,10 @@ cacheable modules 250 bytes ./worker.js 135 bytes [built] [code generated] webpack x.x.x compiled successfully in X ms" `; + +exports[`StatsTestCases should print correct stats for wrong-line-numbers-error 1`] = ` +"ERROR in ./index.js 4:13-33 +Module not found: Error: Can't resolve 'some_file' in 'Xdir/wrong-line-numbers-error' + +webpack compiled with 1 error" +`; diff --git a/test/statsCases/wrong-line-numbers-error/index.js b/test/statsCases/wrong-line-numbers-error/index.js new file mode 100644 index 00000000000..5defbc75f73 --- /dev/null +++ b/test/statsCases/wrong-line-numbers-error/index.js @@ -0,0 +1,3 @@ +// Test: Force Webpack error +const data = require('some_file'); +log(data); diff --git a/test/statsCases/wrong-line-numbers-error/sampleLoader.js b/test/statsCases/wrong-line-numbers-error/sampleLoader.js new file mode 100644 index 00000000000..fb9083b9780 --- /dev/null +++ b/test/statsCases/wrong-line-numbers-error/sampleLoader.js @@ -0,0 +1,3 @@ +module.exports = function(source) { + return `\n\n${source}`; +}; diff --git a/test/statsCases/wrong-line-numbers-error/webpack.config.js b/test/statsCases/wrong-line-numbers-error/webpack.config.js new file mode 100644 index 00000000000..341b053d012 --- /dev/null +++ b/test/statsCases/wrong-line-numbers-error/webpack.config.js @@ -0,0 +1,14 @@ +/** @type {import("../../../../").Configuration} */ + +module.exports = { + entry: "./index", + module: { + rules: [ + { + test: /\.js$/, + use: "./sampleLoader.js" + } + ] + }, + stats: "errors-only" +}; From 7291ad615212d3f27439ec821d077eeb72ec674b Mon Sep 17 00:00:00 2001 From: log101 Date: Sat, 30 Mar 2024 01:26:30 +0300 Subject: [PATCH 2/3] fix: update the loader to include source-map test: update the snapshot --- .../StatsTestCases.basictest.js.snap | 6 +-- .../index.js | 0 .../sampleLoader.js | 40 +++++++++++++++++++ .../webpack.config.js | 1 + .../wrong-line-numbers-error/sampleLoader.js | 3 -- 5 files changed, 44 insertions(+), 6 deletions(-) rename test/statsCases/{wrong-line-numbers-error => wrong-error-location-error}/index.js (100%) create mode 100644 test/statsCases/wrong-error-location-error/sampleLoader.js rename test/statsCases/{wrong-line-numbers-error => wrong-error-location-error}/webpack.config.js (89%) delete mode 100644 test/statsCases/wrong-line-numbers-error/sampleLoader.js diff --git a/test/__snapshots__/StatsTestCases.basictest.js.snap b/test/__snapshots__/StatsTestCases.basictest.js.snap index b2b7674a6b1..977e6c1286b 100644 --- a/test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/test/__snapshots__/StatsTestCases.basictest.js.snap @@ -4816,9 +4816,9 @@ cacheable modules 250 bytes webpack x.x.x compiled successfully in X ms" `; -exports[`StatsTestCases should print correct stats for wrong-line-numbers-error 1`] = ` -"ERROR in ./index.js 4:13-33 -Module not found: Error: Can't resolve 'some_file' in 'Xdir/wrong-line-numbers-error' +exports[`StatsTestCases should print correct stats for wrong-error-location-error 1`] = ` +"ERROR in ./index.js 2:13-33 +Module not found: Error: Can't resolve 'some_file' in 'Xdir/wrong-error-location-error' webpack compiled with 1 error" `; diff --git a/test/statsCases/wrong-line-numbers-error/index.js b/test/statsCases/wrong-error-location-error/index.js similarity index 100% rename from test/statsCases/wrong-line-numbers-error/index.js rename to test/statsCases/wrong-error-location-error/index.js diff --git a/test/statsCases/wrong-error-location-error/sampleLoader.js b/test/statsCases/wrong-error-location-error/sampleLoader.js new file mode 100644 index 00000000000..0f6979ad31e --- /dev/null +++ b/test/statsCases/wrong-error-location-error/sampleLoader.js @@ -0,0 +1,40 @@ +const sourceMap = require("source-map"); + +/** + * + * @param {string|Buffer} source Content of the resource file + */ +function sampleLoader(source) { + var map = new sourceMap.SourceMapGenerator({ + file: "index.js", + }); + + map.addMapping({ + generated: { + line: 4, + column: 13 + }, + original: { + line: 2, + column: 13 + }, + source: "index.js", + }) + + map.addMapping({ + generated: { + line: 4, + column: 33 + }, + original: { + line: 2, + column: 33 + }, + source: "index.js", + }) + + this.callback(null, `\n\n${source}`, map.toJSON()) + return; +} + +module.exports = sampleLoader; diff --git a/test/statsCases/wrong-line-numbers-error/webpack.config.js b/test/statsCases/wrong-error-location-error/webpack.config.js similarity index 89% rename from test/statsCases/wrong-line-numbers-error/webpack.config.js rename to test/statsCases/wrong-error-location-error/webpack.config.js index 341b053d012..e9d2c7cd6f9 100644 --- a/test/statsCases/wrong-line-numbers-error/webpack.config.js +++ b/test/statsCases/wrong-error-location-error/webpack.config.js @@ -10,5 +10,6 @@ module.exports = { } ] }, + devtool: "source-map", stats: "errors-only" }; diff --git a/test/statsCases/wrong-line-numbers-error/sampleLoader.js b/test/statsCases/wrong-line-numbers-error/sampleLoader.js deleted file mode 100644 index fb9083b9780..00000000000 --- a/test/statsCases/wrong-line-numbers-error/sampleLoader.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function(source) { - return `\n\n${source}`; -}; From 9765c3626d8d8dbc9c924f342311e1c6c9afc743 Mon Sep 17 00:00:00 2001 From: log101 Date: Sat, 30 Mar 2024 01:41:19 +0300 Subject: [PATCH 3/3] fix: type import --- test/statsCases/wrong-error-location-error/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/statsCases/wrong-error-location-error/webpack.config.js b/test/statsCases/wrong-error-location-error/webpack.config.js index e9d2c7cd6f9..f4141ae66fe 100644 --- a/test/statsCases/wrong-error-location-error/webpack.config.js +++ b/test/statsCases/wrong-error-location-error/webpack.config.js @@ -1,4 +1,4 @@ -/** @type {import("../../../../").Configuration} */ +/** @type {import("../../../types").Configuration} */ module.exports = { entry: "./index",