Skip to content
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
17 changes: 15 additions & 2 deletions packages/angular_devkit/build_angular/src/sass/sass-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ interface RenderResponseMessage {
result?: Result;
}

/**
* Workaround required for lack of new Worker transfer list support in Node.js prior to 12.17
*/
let transferListWorkaround = false;
const version = process.versions.node.split('.').map((part) => Number(part));
if (version[0] === 12 && version[1] < 17) {
transferListWorkaround = true;
}

/**
* A Sass renderer implementation that provides an interface that can be used by Webpack's
* `sass-loader`. The implementation uses a Worker thread to perform the Sass rendering
Expand Down Expand Up @@ -126,10 +135,14 @@ export class SassWorkerImplementation {

const workerPath = require.resolve('./worker');
const worker = new Worker(workerPath, {
workerData: { workerImporterPort, importerSignal },
transferList: [workerImporterPort],
workerData: transferListWorkaround ? undefined : { workerImporterPort, importerSignal },
transferList: transferListWorkaround ? undefined : [workerImporterPort],
});

if (transferListWorkaround) {
worker.postMessage({ init: true, workerImporterPort, importerSignal }, [workerImporterPort]);
}

worker.on('message', (response: RenderResponseMessage) => {
const request = this.requests.get(response.id);
if (!request) {
Expand Down
31 changes: 25 additions & 6 deletions packages/angular_devkit/build_angular/src/sass/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,46 @@ interface RenderRequestMessage {
* importer on the main thread.
*/
id: number;

/**
* The Sass options to provide to the `dart-sass` render function.
*/
options: Options;

/**
* Indicates the request has a custom importer function on the main thread.
*/
hasImporter: boolean;

/**
* Indicates this is not an init message.
*/
init: undefined;
}

interface InitMessage {
init: true;
workerImporterPort: MessagePort;
importerSignal: Int32Array;
}

if (!parentPort || !workerData) {
if (!parentPort) {
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;
};
let { workerImporterPort, importerSignal } = (workerData || {}) as InitMessage;

parentPort.on('message', (message: RenderRequestMessage | InitMessage) => {
// The init message is only needed to support Node.js < 12.17 and can be removed once support is dropped
if (message.init) {
workerImporterPort = message.workerImporterPort;
importerSignal = message.importerSignal;

return;
}

parentPort.on('message', ({ id, hasImporter, options }: RenderRequestMessage) => {
const { id, hasImporter, options } = message;
try {
if (hasImporter) {
// When a custom importer function is present, the importer request must be proxied
Expand Down