From 004ed385084b3fa1e47bfc061124049716386b1b Mon Sep 17 00:00:00 2001 From: hikiko4ern <25303622+hikiko4ern@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:11:57 +0000 Subject: [PATCH] fix(modern-compiler): dispose redundant compilers (#1245) --- src/utils.js | 2 + ...mentation-option.test.js.no-node-sass.snap | 4 ++ .../implementation-option.test.js.snap | 4 ++ test/implementation-option.test.js | 64 +++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/src/utils.js b/src/utils.js index 76d22b36..4ea78ce6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -768,6 +768,8 @@ function getCompileFn(loaderContext, implementation, apiType) { webpackCompiler.hooks.shutdown.tap("sass-loader", () => { compiler.dispose(); }); + } else { + compiler.dispose(); } } diff --git a/test/__snapshots__/implementation-option.test.js.no-node-sass.snap b/test/__snapshots__/implementation-option.test.js.no-node-sass.snap index 68f8787b..9ac59734 100644 --- a/test/__snapshots__/implementation-option.test.js.no-node-sass.snap +++ b/test/__snapshots__/implementation-option.test.js.no-node-sass.snap @@ -48,6 +48,10 @@ exports[`implementation option not specify: errors 1`] = `[]`; exports[`implementation option not specify: warnings 1`] = `[]`; +exports[`implementation option should dispose redundant compilers for \`modern-compiler\`: errors 1`] = `[]`; + +exports[`implementation option should dispose redundant compilers for \`modern-compiler\`: warnings 1`] = `[]`; + exports[`implementation option should not swallow an error when trying to load a sass implementation: errors 1`] = ` [ "ModuleBuildError: Module build failed (from ../src/cjs.js): diff --git a/test/__snapshots__/implementation-option.test.js.snap b/test/__snapshots__/implementation-option.test.js.snap index 21d95e88..6f8b6c18 100644 --- a/test/__snapshots__/implementation-option.test.js.snap +++ b/test/__snapshots__/implementation-option.test.js.snap @@ -52,6 +52,10 @@ exports[`implementation option not specify: errors 1`] = `[]`; exports[`implementation option not specify: warnings 1`] = `[]`; +exports[`implementation option should dispose redundant compilers for \`modern-compiler\`: errors 1`] = `[]`; + +exports[`implementation option should dispose redundant compilers for \`modern-compiler\`: warnings 1`] = `[]`; + exports[`implementation option should not swallow an error when trying to load a sass implementation: errors 1`] = ` [ "ModuleBuildError: Module build failed (from ../src/cjs.js): diff --git a/test/implementation-option.test.js b/test/implementation-option.test.js index ba11835c..5e699544 100644 --- a/test/implementation-option.test.js +++ b/test/implementation-option.test.js @@ -398,6 +398,70 @@ describe("implementation option", () => { await close(compiler); }); + it("should dispose redundant compilers for `modern-compiler`", async () => { + sassEmbeddedCompilerSpies.mockRestore(); + + let isInRace = false; + + let firstDisposeSpy; + let secondDisposeSpy; + + const actualFn = sassEmbedded.initAsyncCompiler.bind(sassEmbedded); + + const initSpy = jest + .spyOn(sassEmbedded, "initAsyncCompiler") + .mockImplementation(async () => { + const compiler = await actualFn(); + + if (!isInRace) { + firstDisposeSpy = jest.spyOn(compiler, "dispose"); + isInRace = true; + + return new Promise((resolve) => { + const interval = setInterval(() => { + if (!isInRace) { + clearInterval(interval); + resolve(compiler); + } + }); + }); + } + + isInRace = false; + secondDisposeSpy = jest.spyOn(compiler, "dispose"); + + return compiler; + }); + + const testId1 = getTestId("language", "scss"); + const testId2 = getTestId("language", "sass"); + const options = { api: "modern-compiler" }; + + // eslint-disable-next-line no-undefined + const compiler = getCompiler(undefined, { + entry: { + one: `./${testId1}`, + two: `./${testId2}`, + }, + loader: { options }, + }); + const stats = await compile(compiler); + + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + expect(initSpy).toHaveBeenCalledTimes(2); + + await close(compiler); + + initSpy.mockRestore(); + + expect(firstDisposeSpy).toHaveBeenCalledTimes(1); + firstDisposeSpy.mockRestore(); + + expect(secondDisposeSpy).toHaveBeenCalledTimes(1); + secondDisposeSpy.mockRestore(); + }); + it("should try to load using valid order", async () => { jest.doMock("sass", () => { const error = new Error("Some error sass");