-
Notifications
You must be signed in to change notification settings - Fork 295
/
stylesheet-processor.ts
82 lines (69 loc) · 2.16 KB
/
stylesheet-processor.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
70
71
72
73
74
75
76
77
78
79
80
81
82
import * as browserslist from 'browserslist';
import { join } from 'path';
import * as findCacheDirectory from 'find-cache-dir';
import { tmpdir } from 'os';
import { MessageChannel, receiveMessageOnPort, Worker } from 'worker_threads';
import * as log from '../utils/log';
export enum CssUrl {
inline = 'inline',
none = 'none',
}
export interface WorkerOptions {
filePath: string;
basePath: string;
browserslistData: string[];
cssUrl?: CssUrl;
styleIncludePaths?: string[];
cachePath: string;
}
export interface WorkerResult {
css: string;
warnings: string[];
error?: string;
}
export class StylesheetProcessor {
private browserslistData: string[] | undefined;
private worker: Worker | undefined;
private readonly cachePath: string;
constructor(
private readonly basePath: string,
private readonly cssUrl?: CssUrl,
private readonly styleIncludePaths?: string[],
) {
this.cachePath = findCacheDirectory({ name: 'ng-packagr-styles' }) || tmpdir();
}
process(filePath: string) {
if (!this.worker) {
this.worker = new Worker(join(__dirname, './stylesheet-processor-worker.js'));
}
if (!this.browserslistData) {
log.debug(`determine browserslist for ${this.basePath}`);
this.browserslistData = browserslist(undefined, { path: this.basePath });
}
const workerOptions: WorkerOptions = {
filePath,
basePath: this.basePath,
cssUrl: this.cssUrl,
styleIncludePaths: this.styleIncludePaths,
browserslistData: this.browserslistData,
cachePath: this.cachePath,
};
const ioChannel = new MessageChannel();
try {
const signal = new Int32Array(new SharedArrayBuffer(4));
this.worker.postMessage({ signal, port: ioChannel.port1, workerOptions }, [ioChannel.port1]);
// Sleep until signal[0] is 0
Atomics.wait(signal, 0, 0);
const { css, warnings, error } = receiveMessageOnPort(ioChannel.port2).message;
if (error) {
throw new Error(error);
}
warnings.forEach(msg => log.warn(msg));
return css;
} finally {
ioChannel.port1.close();
ioChannel.port2.close();
this.worker.unref();
}
}
}