Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watch previous files if preprocessing failed #132

Merged
merged 2 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,14 @@ export default function sveltePlugin(options?: esbuildSvelteOptions): Plugin {

//main loader
build.onLoad({ filter: svelteFilter }, async (args) => {
let cachedFile = null;
let previousWatchFiles: string[] = [];

// if told to use the cache, check if it contains the file,
// and if the modified time is not greater than the time when it was cached
// if so, return the cached data
if (options?.cache === true && fileCache.has(args.path)) {
const cachedFile = fileCache.get(args.path) || {
cachedFile = fileCache.get(args.path) || {
dependencies: new Map(),
data: null,
}; // should never hit the null b/c of has check
Expand Down Expand Up @@ -177,13 +180,25 @@ export default function sveltePlugin(options?: esbuildSvelteOptions): Plugin {

//do preprocessor stuff if it exists
if (options?.preprocess) {
let preprocessResult = await preprocess(
originalSource,
options.preprocess,
{
filename,
let preprocessResult = null;

try {
preprocessResult = await preprocess(
originalSource,
options.preprocess,
{
filename,
}
);
} catch (e: any) {
// if preprocess failed there are chances that an external dependency caused exception
// to avoid stop watching those files, we keep the previous dependencies if available
if (build.initialOptions.watch && cachedFile) {
previousWatchFiles = Array.from(cachedFile.dependencies.keys());
}
);
throw e;
}

if (preprocessResult.map) {
// normalize the sourcemap 'source' entrys to all match if they are the same file
// needed because of differing handling of file names in preprocessors
Expand Down Expand Up @@ -262,7 +277,7 @@ export default function sveltePlugin(options?: esbuildSvelteOptions): Plugin {

return result;
} catch (e: any) {
return { errors: [convertMessage(e)] };
return { errors: [convertMessage(e)], watchFiles: previousWatchFiles };
}
});

Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/watch-preprocessing/entry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Test from "./external-styles.svelte";

new Test({
target: document.body,
});
7 changes: 7 additions & 0 deletions test/fixtures/watch-preprocessing/external-styles.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<style lang="scss">
@import "./external.scss";
</style>

<div>
<h1>Hello World</h1>
</div>
3 changes: 3 additions & 0 deletions test/fixtures/watch-preprocessing/external.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
p {
color: red;
}
76 changes: 76 additions & 0 deletions test/watchPreprocessingTest.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { test } from "uvu";
import * as assert from "uvu/assert";
import { writeFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname } from "path";
import { build as _build } from "esbuild";
import { sass } from "svelte-preprocess-sass";
import sveltePlugin from "../dist/index.mjs";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

test("Watch and build while preprocess of external dependency succeed and fails", async () => {
function _createDeferred() {
let resolve = null;
let reject = null;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
promise.forceResolve = resolve;
promise.forceReject = reject;
return promise;
}

let count = 0;
const firstRebuild = _createDeferred();
const secondRebuild = _createDeferred();

//more advanced
const results = await _build({
entryPoints: ["./test/fixtures/watch-preprocessing/entry.js"],
outdir: "../example/dist",
format: "esm",
minify: true,
bundle: true,
splitting: true,
write: false, //Don't write anywhere
sourcemap: "inline",
plugins: [
sveltePlugin({
preprocess: {
style: sass(),
},
}),
],
watch: {
onRebuild(err, result) {
count++;
if (count === 1) {
firstRebuild.forceResolve(err);
} else if (count === 2) {
secondRebuild.forceResolve(result);
}
},
},
});

// write external scss with invalid syntax
writeFileSync(
`${__dirname}/fixtures/watch-preprocessing/external.scss`,
"p { color: red; }!$%^&*()@$%^@@"
);
const firstRebuildResult = await firstRebuild;
assert.ok(firstRebuildResult instanceof Error, "First build did not fail");

// write external scss with valid syntax again
writeFileSync(`${__dirname}/fixtures/watch-preprocessing/external.scss`, "p { color: red; }");
const secondRebuildResult = await secondRebuild;
assert.ok(secondRebuildResult.errors.length === 0, "Second build fail");

// stop watching
results.stop();
});

test.run();