Skip to content

Commit 6482a64

Browse files
committed
fix(@angular-devkit/build-angular): ensure Sass worker implementation supports Node.js 12.14
The Worker constructor option for a transfer list is unfortunately not supported until Node.js 12.17. For Node.js versions prior to 12.17, a manual message post is now used to transfer the necessary initialization data to the Sass workers. (cherry picked from commit 4dc7cf9)
1 parent 394a001 commit 6482a64

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

packages/angular_devkit/build_angular/src/sass/sass-service.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ interface RenderResponseMessage {
3939
result?: Result;
4040
}
4141

42+
/**
43+
* Workaround required for lack of new Worker transfer list support in Node.js prior to 12.17
44+
*/
45+
let transferListWorkaround = false;
46+
const version = process.versions.node.split('.').map((part) => Number(part));
47+
if (version[0] === 12 && version[1] < 17) {
48+
transferListWorkaround = true;
49+
}
50+
4251
/**
4352
* A Sass renderer implementation that provides an interface that can be used by Webpack's
4453
* `sass-loader`. The implementation uses a Worker thread to perform the Sass rendering
@@ -126,10 +135,14 @@ export class SassWorkerImplementation {
126135

127136
const workerPath = require.resolve('./worker');
128137
const worker = new Worker(workerPath, {
129-
workerData: { workerImporterPort, importerSignal },
130-
transferList: [workerImporterPort],
138+
workerData: transferListWorkaround ? undefined : { workerImporterPort, importerSignal },
139+
transferList: transferListWorkaround ? undefined : [workerImporterPort],
131140
});
132141

142+
if (transferListWorkaround) {
143+
worker.postMessage({ init: true, workerImporterPort, importerSignal }, [workerImporterPort]);
144+
}
145+
133146
worker.on('message', (response: RenderResponseMessage) => {
134147
const request = this.requests.get(response.id);
135148
if (!request) {

packages/angular_devkit/build_angular/src/sass/worker.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,46 @@ interface RenderRequestMessage {
1818
* importer on the main thread.
1919
*/
2020
id: number;
21+
2122
/**
2223
* The Sass options to provide to the `dart-sass` render function.
2324
*/
2425
options: Options;
26+
2527
/**
2628
* Indicates the request has a custom importer function on the main thread.
2729
*/
2830
hasImporter: boolean;
31+
32+
/**
33+
* Indicates this is not an init message.
34+
*/
35+
init: undefined;
36+
}
37+
38+
interface InitMessage {
39+
init: true;
40+
workerImporterPort: MessagePort;
41+
importerSignal: Int32Array;
2942
}
3043

31-
if (!parentPort || !workerData) {
44+
if (!parentPort) {
3245
throw new Error('Sass worker must be executed as a Worker.');
3346
}
3447

3548
// The importer variables are used to proxy import requests to the main thread
36-
const { workerImporterPort, importerSignal } = workerData as {
37-
workerImporterPort: MessagePort;
38-
importerSignal: Int32Array;
39-
};
49+
let { workerImporterPort, importerSignal } = (workerData || {}) as InitMessage;
50+
51+
parentPort.on('message', (message: RenderRequestMessage | InitMessage) => {
52+
// The init message is only needed to support Node.js < 12.17 and can be removed once support is dropped
53+
if (message.init) {
54+
workerImporterPort = message.workerImporterPort;
55+
importerSignal = message.importerSignal;
56+
57+
return;
58+
}
4059

41-
parentPort.on('message', ({ id, hasImporter, options }: RenderRequestMessage) => {
60+
const { id, hasImporter, options } = message;
4261
try {
4362
if (hasImporter) {
4463
// When a custom importer function is present, the importer request must be proxied

0 commit comments

Comments
 (0)