Skip to content

Commit bc3f23a

Browse files
authored
Merge pull request #369 from jtangelder/fix/368-multi-compilation
Fix bug where multiple compilations interfered with each other
2 parents b387510 + 8d54166 commit bc3f23a

File tree

10 files changed

+77
-4
lines changed

10 files changed

+77
-4
lines changed

lib/normalizeOptions.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ const proxyCustomImporters = require("./proxyCustomImporters");
88
/**
99
* Derives the sass options from the loader context and normalizes its values with sane defaults.
1010
*
11+
* Please note: If loaderContext.query is an options object, it will be re-used across multiple invocations.
12+
* That's why we must not modify the object directly.
13+
*
1114
* @param {LoaderContext} loaderContext
1215
* @param {string} content
1316
* @param {Function} webpackImporter
1417
* @returns {Object}
1518
*/
1619
function normalizeOptions(loaderContext, content, webpackImporter) {
17-
const options = utils.parseQuery(loaderContext.query);
20+
const options = loaderContext.query && typeof loaderContext.query === "object" ?
21+
// Make a copy of the query object
22+
// @see https://github.com/jtangelder/sass-loader/issues/368#issuecomment-278330164
23+
Object.assign({}, loaderContext.query) :
24+
utils.parseQuery(loaderContext.query);
25+
1826
const resourcePath = loaderContext.resourcePath;
1927

2028
options.data = options.data ? (options.data + os.EOL + content) : content;

test/index.test.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ syntaxStyles.forEach(ext => {
3939

4040
runWebpack(baseConfig, (err) => err ? reject(err) : resolve());
4141
}).then(() => {
42-
delete require.cache[path.resolve(__dirname, "./output/bundle." + ext + ".js")];
43-
44-
const actualCss = require("./output/bundle." + ext + ".js");
42+
const actualCss = readBundle("bundle." + ext + ".js");
4543
const expectedCss = readCss(ext, testId);
4644

4745
// writing the actual css to output-dir for better debugging
@@ -86,6 +84,59 @@ syntaxStyles.forEach(ext => {
8684
});
8785

8886
describe("sass-loader", () => {
87+
describe("multiple compilations", () => {
88+
it("should not interfere with each other", () =>
89+
new Promise((resolve, reject) => {
90+
runWebpack({
91+
entry: {
92+
b: path.join(__dirname, "scss", "multipleCompilations", "b.scss"),
93+
c: path.join(__dirname, "scss", "multipleCompilations", "c.scss"),
94+
a: path.join(__dirname, "scss", "multipleCompilations", "a.scss"),
95+
d: path.join(__dirname, "scss", "multipleCompilations", "d.scss"),
96+
e: path.join(__dirname, "scss", "multipleCompilations", "e.scss"),
97+
f: path.join(__dirname, "scss", "multipleCompilations", "f.scss"),
98+
g: path.join(__dirname, "scss", "multipleCompilations", "g.scss"),
99+
h: path.join(__dirname, "scss", "multipleCompilations", "h.scss")
100+
},
101+
output: {
102+
filename: "bundle.multiple-compilations.[name].js"
103+
},
104+
module: {
105+
rules: [{
106+
test: /\.scss$/,
107+
use: [
108+
{ loader: "raw-loader" },
109+
// We're specifying an empty options object because otherwise, webpack creates a new object for every loader invocation
110+
// Since we want to ensure that our loader is not tampering with the option object, we are triggering webpack to re-use the options object
111+
// @see https://github.com/jtangelder/sass-loader/issues/368#issuecomment-278330164
112+
{ loader: pathToSassLoader, options: {} }
113+
]
114+
}]
115+
}
116+
}, (err) => err ? reject(err) : resolve());
117+
})
118+
.then(() => {
119+
const expectedCss = readCss("scss", "imports");
120+
const a = readBundle("bundle.multiple-compilations.a.js");
121+
const b = readBundle("bundle.multiple-compilations.b.js");
122+
const c = readBundle("bundle.multiple-compilations.c.js");
123+
const d = readBundle("bundle.multiple-compilations.d.js");
124+
const e = readBundle("bundle.multiple-compilations.e.js");
125+
const f = readBundle("bundle.multiple-compilations.f.js");
126+
const g = readBundle("bundle.multiple-compilations.g.js");
127+
const h = readBundle("bundle.multiple-compilations.h.js");
128+
129+
a.should.equal(expectedCss);
130+
b.should.equal(expectedCss);
131+
c.should.equal(expectedCss);
132+
d.should.equal(expectedCss);
133+
e.should.equal(expectedCss);
134+
f.should.equal(expectedCss);
135+
g.should.equal(expectedCss);
136+
h.should.equal(expectedCss);
137+
})
138+
);
139+
});
89140
describe("errors", () => {
90141
it("should throw an error in synchronous loader environments", () => {
91142
try {
@@ -164,3 +215,9 @@ function runWebpack(baseConfig, done) {
164215
done(err || null);
165216
});
166217
}
218+
219+
function readBundle(filename) {
220+
delete require.cache[path.resolve(__dirname, `./output/${ filename }`)];
221+
222+
return require(`./output/${ filename }`);
223+
}

test/scss/multipleCompilations/a.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/b.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/c.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/d.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/e.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/f.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/g.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

test/scss/multipleCompilations/h.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "../imports";

0 commit comments

Comments
 (0)