Skip to content

Commit c7b7820

Browse files
committed
Land ESM-based config support without requiring opt-in
1 parent dc4483f commit c7b7820

File tree

48 files changed

+196
-550
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+196
-550
lines changed

eslint-plugin-helper.js

Lines changed: 34 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,49 @@
11
'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');
414

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');
596

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.
668

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;
7012

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);
7817

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);
8320

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}
11326
}
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();
12929
} 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+
}
14232

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);
14734

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');
15138
}
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+
};
15347

15448
const helperCache = new Map();
15549

lib/eslint-plugin-helper-worker.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'use strict';
2+
const v8 = require('v8');
3+
const {parentPort, workerData} = require('worker_threads');
4+
5+
const {normalizeGlobs} = require('./globs');
6+
const normalizeExtensions = require('./extensions');
7+
const {loadConfig} = require('./load-config');
8+
const providerManager = require('./provider-manager');
9+
10+
const MAX_DATA_LENGTH_EXCLUSIVE = 100 * 1024; // Allocate 100 KiB to exchange globs.
11+
12+
const configCache = new Map();
13+
14+
const collectProviders = ({conf, projectDir}) => {
15+
const providers = [];
16+
if (Reflect.has(conf, 'babel')) {
17+
const {level, main} = providerManager.babel(projectDir);
18+
providers.push({
19+
level,
20+
main: main({config: conf.babel}),
21+
type: 'babel'
22+
});
23+
}
24+
25+
if (Reflect.has(conf, 'typescript')) {
26+
const {level, main} = providerManager.typescript(projectDir);
27+
providers.push({
28+
level,
29+
main: main({config: conf.typescript}),
30+
type: 'typescript'
31+
});
32+
}
33+
34+
return providers;
35+
};
36+
37+
const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFiles}) => {
38+
const extensions = overrideExtensions ?
39+
normalizeExtensions(overrideExtensions) :
40+
normalizeExtensions(conf.extensions, providers);
41+
42+
return {
43+
cwd: projectDir,
44+
...normalizeGlobs({
45+
extensions,
46+
files: overrideFiles ? overrideFiles : conf.files,
47+
providers
48+
})
49+
};
50+
};
51+
52+
const resolveGlobs = async (projectDir, overrideExtensions, overrideFiles) => {
53+
if (!configCache.has(projectDir)) {
54+
configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(conf => { // eslint-disable-line promise/prefer-await-to-then
55+
const providers = collectProviders({conf, projectDir});
56+
return {conf, providers};
57+
}));
58+
}
59+
60+
const {conf, providers} = await configCache.get(projectDir);
61+
return buildGlobs({conf, providers, projectDir, overrideExtensions, overrideFiles});
62+
};
63+
64+
const data = new Uint8Array(workerData.dataBuffer);
65+
const sync = new Int32Array(workerData.syncBuffer);
66+
67+
const handleMessage = async ({projectDir, overrideExtensions, overrideFiles}) => {
68+
let encoded;
69+
try {
70+
const globs = await resolveGlobs(projectDir, overrideExtensions, overrideFiles);
71+
encoded = v8.serialize(globs);
72+
} catch (error) {
73+
encoded = v8.serialize(error);
74+
}
75+
76+
const byteLength = encoded.length < MAX_DATA_LENGTH_EXCLUSIVE ? encoded.copy(data) : MAX_DATA_LENGTH_EXCLUSIVE;
77+
Atomics.store(sync, 0, byteLength);
78+
Atomics.notify(sync, 0);
79+
};
80+
81+
parentPort.on('message', handleMessage);
82+
handleMessage(workerData.firstMessage);
83+
delete workerData.firstMessage;

0 commit comments

Comments
 (0)