diff --git a/src/index.js b/src/index.js index ec7e30d..8f31132 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ Author Tobias Koppers @sokra */ -import { SourceNode, SourceMapConsumer } from "source-map"; +import { SourceNode, SourceMapConsumer, SourceMapGenerator } from "source-map"; import schema from "./options.json"; @@ -74,18 +74,36 @@ export default function loader(content, sourceMap) { codeAfterModule += `\n}.call(${thisArg}${args ? `, ${args}` : ""}));\n`; } - if (this.sourceMap && sourceMap) { - const node = SourceNode.fromStringWithSourceMap( - content, - new SourceMapConsumer(sourceMap) - ); + if (this.sourceMap) { + if (sourceMap) { + const node = SourceNode.fromStringWithSourceMap( + content, + new SourceMapConsumer(sourceMap) + ); + + node.prepend(`${importsCode}\n`); + node.add(codeAfterModule); - node.prepend(`${importsCode}\n`); - node.add(codeAfterModule); + const result = node.toStringWithSourceMap({ file: this.resourcePath }); - const result = node.toStringWithSourceMap({ file: this.resourcePath }); + callback(null, result.code, result.map.toJSON()); - callback(null, result.code, result.map.toJSON()); + return; + } + const generator = new SourceMapGenerator(); + + generator.setSourceContent(this.resourcePath, content); + generator.addMapping({ + generated: { line: importsCode.split("\n").length + 1, column: 0 }, + original: { line: 1, column: 0 }, + source: this.resourcePath, + }); + + callback( + null, + `${importsCode}\n${content}\n${codeAfterModule}`, + generator.toString() + ); return; } diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index 15791d4..e818a95 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -1,21 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`loader should not work with source maps when the "devtool" options are disabled: errors 1`] = `Array []`; - -exports[`loader should not work with source maps when the "devtool" options are disabled: module 1`] = ` -"/*** IMPORTS FROM imports-loader ***/ -import lib_1 from \\"lib_1\\"; - -var someCode = { - number: 123, - object: { - existingSubProperty: 123 - } -};" -`; - -exports[`loader should not work with source maps when the "devtool" options are disabled: warnings 1`] = `Array []`; - exports[`loader should throw an error on the empty string: errors 1`] = ` Array [ "ModuleBuildError: Module build failed (from \`replaced original path\`): @@ -1113,22 +1097,6 @@ var someCode = { exports[`loader should work with relative requests: warnings 1`] = `Array []`; -exports[`loader should work with source maps when the "devtool" option is enabled: errors 1`] = `Array []`; - -exports[`loader should work with source maps when the "devtool" option is enabled: module 1`] = ` -"/*** IMPORTS FROM imports-loader ***/ -import lib_1 from \\"lib_1\\"; - -var someCode = { - number: 123, - object: { - existingSubProperty: 123 - } -};" -`; - -exports[`loader should work with source maps when the "devtool" option is enabled: warnings 1`] = `Array []`; - exports[`loader should work with the "additionalCode" option: errors 1`] = `Array []`; exports[`loader should work with the "additionalCode" option: module 1`] = ` diff --git a/test/loader.test.js b/test/loader.test.js index 75aa3c7..d8a26ff 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -1,5 +1,7 @@ import path from "path"; +import { SourceMapConsumer } from "source-map"; + import { compile, getCompiler, @@ -7,6 +9,7 @@ import { getModuleSource, getWarnings, } from "./helpers"; +import readAsset from "./helpers/readAsset"; describe("loader", () => { it("should work with a string value", async () => { @@ -307,7 +310,7 @@ describe("loader", () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); }); - it('should work with source maps when the "devtool" option is enabled', async () => { + it('should generate source maps when the "devtool" option is enabled', async () => { const compiler = getCompiler( "some-library.js", {}, @@ -322,9 +325,6 @@ describe("loader", () => { loader: path.resolve(__dirname, "../src"), options: { imports: "lib_1" }, }, - { - loader: "babel-loader", - }, ], }, ], @@ -332,20 +332,32 @@ describe("loader", () => { } ); const stats = await compile(compiler); - - expect(getModuleSource("./some-library.js", stats)).toMatchSnapshot( - "module" + const bundle = readAsset( + "main.bundle.js", + stats.compilation.compiler, + stats + ).split("\n"); + const sourceMap = readAsset( + "main.bundle.js.map", + stats.compilation.compiler, + stats ); - expect(getErrors(stats)).toMatchSnapshot("errors"); - expect(getWarnings(stats)).toMatchSnapshot("warnings"); + + const consumer = new SourceMapConsumer(sourceMap); + const result = consumer.generatedPositionFor({ + line: 1, + column: 0, + source: "webpack://ImportsLoader/some-library.js", + }); + expect(bundle[result.line - 1 /* 1-indexed */]).toEqual("var someCode = {"); }); - it('should not work with source maps when the "devtool" options are disabled', async () => { + it('should update source maps from previous loaders when the "devtool" option is enabled', async () => { const compiler = getCompiler( "some-library.js", {}, { - devtool: false, + devtool: "source-map", module: { rules: [ { @@ -355,9 +367,7 @@ describe("loader", () => { loader: path.resolve(__dirname, "../src"), options: { imports: "lib_1" }, }, - { - loader: "babel-loader", - }, + { loader: "babel-loader" }, ], }, ], @@ -365,12 +375,24 @@ describe("loader", () => { } ); const stats = await compile(compiler); - - expect(getModuleSource("./some-library.js", stats)).toMatchSnapshot( - "module" + const bundle = readAsset( + "main.bundle.js", + stats.compilation.compiler, + stats + ).split("\n"); + const sourceMap = readAsset( + "main.bundle.js.map", + stats.compilation.compiler, + stats ); - expect(getErrors(stats)).toMatchSnapshot("errors"); - expect(getWarnings(stats)).toMatchSnapshot("warnings"); + + const consumer = new SourceMapConsumer(sourceMap); + const result = consumer.generatedPositionFor({ + line: 1, + column: 0, + source: "webpack://ImportsLoader/some-library.js", + }); + expect(bundle[result.line - 1 /* 1-indexed */]).toEqual("var someCode = {"); }); it('should work with "default" imports without syntax', async () => {