-
Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathworker-legacy.ts
69 lines (61 loc) · 2.52 KB
/
worker-legacy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { ImporterResult, LegacyOptions as Options, renderSync } from 'sass';
import { MessagePort, parentPort, receiveMessageOnPort, workerData } from 'worker_threads';
/**
* A request to render a Sass stylesheet using the supplied options.
*/
interface RenderRequestMessage {
/**
* The unique request identifier that links the render action with a callback and optional
* importer on the main thread.
*/
id: number;
/**
* The Sass options to provide to the `dart-sass` render function.
*/
options: Options<'sync'>;
/**
* Indicates the request has a custom importer function on the main thread.
*/
hasImporter: boolean;
}
if (!parentPort || !workerData) {
throw new Error('Sass worker must be executed as a Worker.');
}
// The importer variables are used to proxy import requests to the main thread
const { workerImporterPort, importerSignal } = workerData as {
workerImporterPort: MessagePort;
importerSignal: Int32Array;
};
parentPort.on('message', ({ id, hasImporter, options }: RenderRequestMessage) => {
try {
if (hasImporter) {
// When a custom importer function is present, the importer request must be proxied
// back to the main thread where it can be executed.
// This process must be synchronous from the perspective of dart-sass. The `Atomics`
// functions combined with the shared memory `importSignal` and the Node.js
// `receiveMessageOnPort` function are used to ensure synchronous behavior.
options.importer = function (url, prev) {
Atomics.store(importerSignal, 0, 0);
const { fromImport } = this;
workerImporterPort.postMessage({ id, url, prev, fromImport });
Atomics.wait(importerSignal, 0, 0);
return receiveMessageOnPort(workerImporterPort)?.message as ImporterResult;
};
}
// The synchronous Sass render function can be up to two times faster than the async variant
const result = renderSync(options);
parentPort?.postMessage({ id, result });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
// Needed because V8 will only serialize the message and stack properties of an Error instance.
const { formatted, file, line, column, message, stack } = error;
parentPort?.postMessage({ id, error: { formatted, file, line, column, message, stack } });
}
});