forked from babel/babel
/
client.cjs
108 lines (89 loc) 路 3 KB
/
client.cjs
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
const path = require("path");
const ACTIONS = {
GET_VERSION: "GET_VERSION",
GET_TYPES_INFO: "GET_TYPES_INFO",
GET_VISITOR_KEYS: "GET_VISITOR_KEYS",
GET_TOKEN_LABELS: "GET_TOKEN_LABELS",
MAYBE_PARSE: "MAYBE_PARSE",
MAYBE_PARSE_SYNC: "MAYBE_PARSE_SYNC",
};
class Client {
#send;
constructor(send) {
this.#send = send;
}
#vCache;
getVersion() {
return (this.#vCache ??= this.#send(ACTIONS.GET_VERSION, undefined));
}
#tiCache;
getTypesInfo() {
return (this.#tiCache ??= this.#send(ACTIONS.GET_TYPES_INFO, undefined));
}
#vkCache;
getVisitorKeys() {
return (this.#vkCache ??= this.#send(ACTIONS.GET_VISITOR_KEYS, undefined));
}
#tlCache;
getTokLabels() {
return (this.#tlCache ??= this.#send(ACTIONS.GET_TOKEN_LABELS, undefined));
}
maybeParse(code, options) {
return this.#send(ACTIONS.MAYBE_PARSE, { code, options });
}
}
// We need to run Babel in a worker for two reasons:
// 1. ESLint workers must be CJS files, and this is a problem
// since Babel 8+ uses native ESM
// 2. ESLint parsers must run synchronously, but many steps
// of Babel's config loading (which is done for each file)
// can be asynchronous
// If ESLint starts supporting async parsers, we can move
// everything back to the main thread.
exports.WorkerClient = class WorkerClient extends Client {
static #worker_threads_cache;
static get #worker_threads() {
return (WorkerClient.#worker_threads_cache ??= require("worker_threads"));
}
#worker = new WorkerClient.#worker_threads.Worker(
path.resolve(__dirname, "../lib/worker/index.cjs"),
{ env: WorkerClient.#worker_threads.SHARE_ENV },
);
constructor() {
super((action, payload) => {
// We create a new SharedArrayBuffer every time rather than reusing
// the same one, otherwise sometimes its contents get corrupted and
// Atomics.wait wakes up too early.
// https://github.com/babel/babel/pull/14541
const signal = new Int32Array(new SharedArrayBuffer(8));
const subChannel = new WorkerClient.#worker_threads.MessageChannel();
this.#worker.postMessage(
{ signal, port: subChannel.port1, action, payload },
[subChannel.port1],
);
Atomics.wait(signal, 0, 0);
const { message } = WorkerClient.#worker_threads.receiveMessageOnPort(
subChannel.port2,
);
if (message.error) throw Object.assign(message.error, message.errorData);
else return message.result;
});
// The worker will never exit by itself. Prevent it from keeping
// the main process alive.
this.#worker.unref();
}
};
if (!process.env.BABEL_8_BREAKING) {
exports.LocalClient = class LocalClient extends Client {
static #handleMessage;
constructor() {
LocalClient.#handleMessage ??= require("./worker/handle-message.cjs");
super((action, payload) => {
return LocalClient.#handleMessage(
action === ACTIONS.MAYBE_PARSE ? ACTIONS.MAYBE_PARSE_SYNC : action,
payload,
);
});
}
};
}