|
1 | 1 | 'use strict'; |
2 | | -// TODO: Clean up. |
3 | | -let isMainThread = true; |
4 | | -let supportsWorkers = false; |
5 | | -try { |
6 | | - ({isMainThread} = require('worker_threads')); |
7 | | - supportsWorkers = true; |
8 | | -} catch {} |
9 | | - |
10 | | -const {classify, hasExtension, isHelperish, matches, normalizeFileForMatching, normalizeGlobs, normalizePatterns} = require('./lib/globs'); |
11 | | - |
12 | | -let resolveGlobs; |
13 | | -let resolveGlobsSync; |
14 | | - |
15 | | -if (!supportsWorkers || !isMainThread) { |
16 | | - const normalizeExtensions = require('./lib/extensions'); |
17 | | - const {loadConfig, loadConfigSync} = require('./lib/load-config'); |
18 | | - const providerManager = require('./lib/provider-manager'); |
19 | | - |
20 | | - const configCache = new Map(); |
21 | | - |
22 | | - const collectProviders = ({conf, projectDir}) => { |
23 | | - const providers = []; |
24 | | - if (Reflect.has(conf, 'babel')) { |
25 | | - const {level, main} = providerManager.babel(projectDir); |
26 | | - providers.push({ |
27 | | - level, |
28 | | - main: main({config: conf.babel}), |
29 | | - type: 'babel' |
30 | | - }); |
31 | | - } |
32 | | - |
33 | | - if (Reflect.has(conf, 'typescript')) { |
34 | | - const {level, main} = providerManager.typescript(projectDir); |
35 | | - providers.push({ |
36 | | - level, |
37 | | - main: main({config: conf.typescript}), |
38 | | - type: 'typescript' |
39 | | - }); |
40 | | - } |
| 2 | +const v8 = require('v8'); |
| 3 | +const {Worker} = require('worker_threads'); |
41 | 4 |
|
42 | | - return providers; |
43 | | - }; |
44 | | - |
45 | | - const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFiles}) => { |
46 | | - const extensions = overrideExtensions ? |
47 | | - normalizeExtensions(overrideExtensions) : |
48 | | - normalizeExtensions(conf.extensions, providers); |
49 | | - |
50 | | - return { |
51 | | - cwd: projectDir, |
52 | | - ...normalizeGlobs({ |
53 | | - extensions, |
54 | | - files: overrideFiles ? overrideFiles : conf.files, |
55 | | - providers |
56 | | - }) |
57 | | - }; |
58 | | - }; |
| 5 | +const {classify, hasExtension, isHelperish, matches, normalizeFileForMatching, normalizePatterns} = require('./lib/globs'); |
59 | 6 |
|
60 | | - resolveGlobsSync = (projectDir, overrideExtensions, overrideFiles) => { |
61 | | - if (!configCache.has(projectDir)) { |
62 | | - const conf = loadConfigSync({resolveFrom: projectDir}); |
63 | | - const providers = collectProviders({conf, projectDir}); |
64 | | - configCache.set(projectDir, {conf, providers}); |
65 | | - } |
| 7 | +const MAX_DATA_LENGTH_EXCLUSIVE = 100 * 1024; // Allocate 100 KiB to exchange globs. |
66 | 8 |
|
67 | | - const {conf, providers} = configCache.get(projectDir); |
68 | | - return buildGlobs({conf, providers, projectDir, overrideExtensions, overrideFiles}); |
69 | | - }; |
| 9 | +let data; |
| 10 | +let sync; |
| 11 | +let worker; |
70 | 12 |
|
71 | | - resolveGlobs = async (projectDir, overrideExtensions, overrideFiles) => { |
72 | | - if (!configCache.has(projectDir)) { |
73 | | - configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(conf => { // eslint-disable-line promise/prefer-await-to-then |
74 | | - const providers = collectProviders({conf, projectDir}); |
75 | | - return {conf, providers}; |
76 | | - })); |
77 | | - } |
| 13 | +const resolveGlobsSync = (projectDir, overrideExtensions, overrideFiles) => { |
| 14 | + if (worker === undefined) { |
| 15 | + const dataBuffer = new SharedArrayBuffer(MAX_DATA_LENGTH_EXCLUSIVE); |
| 16 | + data = new Uint8Array(dataBuffer); |
78 | 17 |
|
79 | | - const {conf, providers} = await configCache.get(projectDir); |
80 | | - return buildGlobs({conf, providers, projectDir, overrideExtensions, overrideFiles}); |
81 | | - }; |
82 | | -} |
| 18 | + const syncBuffer = new SharedArrayBuffer(4); |
| 19 | + sync = new Int32Array(syncBuffer); |
83 | 20 |
|
84 | | -if (supportsWorkers) { |
85 | | - const v8 = require('v8'); |
86 | | - |
87 | | - const MAX_DATA_LENGTH_EXCLUSIVE = 100 * 1024; // Allocate 100 KiB to exchange globs. |
88 | | - |
89 | | - if (isMainThread) { |
90 | | - const {Worker} = require('worker_threads'); |
91 | | - let data; |
92 | | - let sync; |
93 | | - let worker; |
94 | | - |
95 | | - resolveGlobsSync = (projectDir, overrideExtensions, overrideFiles) => { |
96 | | - if (worker === undefined) { |
97 | | - const dataBuffer = new SharedArrayBuffer(MAX_DATA_LENGTH_EXCLUSIVE); |
98 | | - data = new Uint8Array(dataBuffer); |
99 | | - |
100 | | - const syncBuffer = new SharedArrayBuffer(4); |
101 | | - sync = new Int32Array(syncBuffer); |
102 | | - |
103 | | - worker = new Worker(__filename, { |
104 | | - workerData: { |
105 | | - dataBuffer, |
106 | | - syncBuffer, |
107 | | - firstMessage: {projectDir, overrideExtensions, overrideFiles} |
108 | | - } |
109 | | - }); |
110 | | - worker.unref(); |
111 | | - } else { |
112 | | - worker.postMessage({projectDir, overrideExtensions, overrideFiles}); |
| 21 | + worker = new Worker('./lib/eslint-plugin-helper-worker.js', { |
| 22 | + workerData: { |
| 23 | + dataBuffer, |
| 24 | + syncBuffer, |
| 25 | + firstMessage: {projectDir, overrideExtensions, overrideFiles} |
113 | 26 | } |
114 | | - |
115 | | - Atomics.wait(sync, 0, 0); |
116 | | - |
117 | | - const byteLength = Atomics.exchange(sync, 0, 0); |
118 | | - if (byteLength === MAX_DATA_LENGTH_EXCLUSIVE) { |
119 | | - throw new Error('Globs are over 100 KiB and cannot be resolved'); |
120 | | - } |
121 | | - |
122 | | - const globsOrError = v8.deserialize(data.slice(0, byteLength)); |
123 | | - if (globsOrError instanceof Error) { |
124 | | - throw globsOrError; |
125 | | - } |
126 | | - |
127 | | - return globsOrError; |
128 | | - }; |
| 27 | + }); |
| 28 | + worker.unref(); |
129 | 29 | } else { |
130 | | - const {parentPort, workerData} = require('worker_threads'); |
131 | | - const data = new Uint8Array(workerData.dataBuffer); |
132 | | - const sync = new Int32Array(workerData.syncBuffer); |
133 | | - |
134 | | - const handleMessage = async ({projectDir, overrideExtensions, overrideFiles}) => { |
135 | | - let encoded; |
136 | | - try { |
137 | | - const globs = await resolveGlobs(projectDir, overrideExtensions, overrideFiles); |
138 | | - encoded = v8.serialize(globs); |
139 | | - } catch (error) { |
140 | | - encoded = v8.serialize(error); |
141 | | - } |
| 30 | + worker.postMessage({projectDir, overrideExtensions, overrideFiles}); |
| 31 | + } |
142 | 32 |
|
143 | | - const byteLength = encoded.length < MAX_DATA_LENGTH_EXCLUSIVE ? encoded.copy(data) : MAX_DATA_LENGTH_EXCLUSIVE; |
144 | | - Atomics.store(sync, 0, byteLength); |
145 | | - Atomics.notify(sync, 0); |
146 | | - }; |
| 33 | + Atomics.wait(sync, 0, 0); |
147 | 34 |
|
148 | | - parentPort.on('message', handleMessage); |
149 | | - handleMessage(workerData.firstMessage); |
150 | | - delete workerData.firstMessage; |
| 35 | + const byteLength = Atomics.exchange(sync, 0, 0); |
| 36 | + if (byteLength === MAX_DATA_LENGTH_EXCLUSIVE) { |
| 37 | + throw new Error('Globs are over 100 KiB and cannot be resolved'); |
151 | 38 | } |
152 | | -} |
| 39 | + |
| 40 | + const globsOrError = v8.deserialize(data.slice(0, byteLength)); |
| 41 | + if (globsOrError instanceof Error) { |
| 42 | + throw globsOrError; |
| 43 | + } |
| 44 | + |
| 45 | + return globsOrError; |
| 46 | +}; |
153 | 47 |
|
154 | 48 | const helperCache = new Map(); |
155 | 49 |
|
|
0 commit comments