@atlaspack/core 2.30.2 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/Atlaspack.js +2 -0
- package/dist/Transformation.js +24 -1
- package/dist/atlaspack-v3/AtlaspackV3.js +3 -0
- package/dist/atlaspack-v3/NapiWorkerPool.js +10 -0
- package/dist/atlaspack-v3/worker/compat/plugin-config.js +10 -22
- package/dist/atlaspack-v3/worker/compat/plugin-options.js +15 -0
- package/dist/atlaspack-v3/worker/side-effect-detector.js +243 -0
- package/dist/atlaspack-v3/worker/worker.js +140 -66
- package/dist/requests/ConfigRequest.js +24 -0
- package/lib/Atlaspack.js +5 -1
- package/lib/Transformation.js +31 -1
- package/lib/atlaspack-v3/AtlaspackV3.js +3 -0
- package/lib/atlaspack-v3/NapiWorkerPool.js +10 -0
- package/lib/atlaspack-v3/worker/compat/plugin-config.js +8 -27
- package/lib/atlaspack-v3/worker/compat/plugin-options.js +15 -0
- package/lib/atlaspack-v3/worker/side-effect-detector.js +215 -0
- package/lib/atlaspack-v3/worker/worker.js +152 -72
- package/lib/requests/ConfigRequest.js +25 -0
- package/lib/types/InternalConfig.d.ts +1 -2
- package/lib/types/atlaspack-v3/AtlaspackV3.d.ts +2 -1
- package/lib/types/atlaspack-v3/NapiWorkerPool.d.ts +1 -0
- package/lib/types/atlaspack-v3/index.d.ts +1 -0
- package/lib/types/atlaspack-v3/worker/compat/plugin-config.d.ts +3 -11
- package/lib/types/atlaspack-v3/worker/compat/plugin-options.d.ts +1 -0
- package/lib/types/atlaspack-v3/worker/side-effect-detector.d.ts +76 -0
- package/lib/types/atlaspack-v3/worker/worker.d.ts +26 -6
- package/lib/types/requests/ConfigRequest.d.ts +9 -1
- package/package.json +14 -14
- package/src/Atlaspack.ts +2 -0
- package/src/InternalConfig.ts +1 -1
- package/src/Transformation.ts +37 -2
- package/src/atlaspack-v3/AtlaspackV3.ts +8 -0
- package/src/atlaspack-v3/NapiWorkerPool.ts +17 -0
- package/src/atlaspack-v3/index.ts +1 -0
- package/src/atlaspack-v3/worker/compat/plugin-config.ts +8 -40
- package/src/atlaspack-v3/worker/compat/plugin-options.ts +15 -0
- package/src/atlaspack-v3/worker/side-effect-detector.ts +298 -0
- package/src/atlaspack-v3/worker/worker.ts +288 -172
- package/src/requests/ConfigRequest.ts +39 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/* eslint-disable import/first */
|
|
2
|
+
import {SideEffectDetector} from './side-effect-detector';
|
|
3
|
+
|
|
4
|
+
// Install side effect detection patches BEFORE importing any modules that use fs
|
|
5
|
+
const sideEffectDetector = new SideEffectDetector();
|
|
6
|
+
sideEffectDetector.install();
|
|
7
|
+
|
|
1
8
|
import assert from 'assert';
|
|
2
9
|
import * as napi from '@atlaspack/rust';
|
|
3
10
|
// @ts-expect-error TS2305
|
|
@@ -10,6 +17,7 @@ import type {
|
|
|
10
17
|
FilePath,
|
|
11
18
|
FileSystem,
|
|
12
19
|
} from '@atlaspack/types';
|
|
20
|
+
import type {FeatureFlags} from '@atlaspack/feature-flags';
|
|
13
21
|
import {parentPort} from 'worker_threads';
|
|
14
22
|
import * as module from 'module';
|
|
15
23
|
|
|
@@ -25,7 +33,6 @@ import {
|
|
|
25
33
|
bundleBehaviorMap,
|
|
26
34
|
dependencyPriorityMap,
|
|
27
35
|
} from './compat';
|
|
28
|
-
import {FeatureFlags} from '@atlaspack/feature-flags';
|
|
29
36
|
|
|
30
37
|
const CONFIG = Symbol.for('parcel-plugin-config');
|
|
31
38
|
|
|
@@ -34,16 +41,25 @@ export class AtlaspackWorker {
|
|
|
34
41
|
#transformers: Map<string, TransformerState<any>>;
|
|
35
42
|
#fs: FileSystem;
|
|
36
43
|
#packageManager: NodePackageManager;
|
|
44
|
+
#options: Options | undefined;
|
|
45
|
+
#sideEffectDetector: SideEffectDetector;
|
|
37
46
|
|
|
38
47
|
constructor() {
|
|
39
48
|
this.#resolvers = new Map();
|
|
40
49
|
this.#transformers = new Map();
|
|
41
50
|
this.#fs = new NodeFS();
|
|
42
51
|
this.#packageManager = new NodePackageManager(this.#fs, '/');
|
|
52
|
+
this.#sideEffectDetector = sideEffectDetector; // Use the global detector that was installed before imports
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
clearState() {
|
|
56
|
+
this.#resolvers.clear();
|
|
57
|
+
this.#transformers.clear();
|
|
58
|
+
this.#options = undefined;
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
loadPlugin: JsCallable<[LoadPluginOptions], Promise<undefined>> = jsCallable(
|
|
46
|
-
async ({kind, specifier, resolveFrom,
|
|
62
|
+
async ({kind, specifier, resolveFrom, options}) => {
|
|
47
63
|
// Use packageManager.require() instead of dynamic import() to support TypeScript plugins
|
|
48
64
|
let resolvedModule = await this.#packageManager.require(
|
|
49
65
|
specifier,
|
|
@@ -70,26 +86,32 @@ export class AtlaspackWorker {
|
|
|
70
86
|
`Plugin could not be resolved\n\t${kind}\n\t${resolveFrom}\n\t${specifier}`,
|
|
71
87
|
);
|
|
72
88
|
}
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
|
|
90
|
+
if (this.#options == null) {
|
|
91
|
+
this.#options = {
|
|
92
|
+
...options,
|
|
93
|
+
inputFS: this.#fs,
|
|
94
|
+
outputFS: this.#fs,
|
|
95
|
+
packageManager: this.#packageManager,
|
|
96
|
+
shouldAutoInstall: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
75
100
|
// Set feature flags in the worker process
|
|
76
101
|
let featureFlagsModule = await this.#packageManager.require(
|
|
77
102
|
'@atlaspack/feature-flags',
|
|
78
103
|
__filename,
|
|
79
104
|
{shouldAutoInstall: false},
|
|
80
105
|
);
|
|
81
|
-
featureFlagsModule.setFeatureFlags(featureFlags);
|
|
82
|
-
// const {setFeatureFlags} = await import('@atlaspack/feature-flags');
|
|
83
|
-
// setFeatureFlags(featureFlags);
|
|
84
|
-
// }
|
|
106
|
+
featureFlagsModule.setFeatureFlags(options.featureFlags);
|
|
85
107
|
|
|
86
108
|
switch (kind) {
|
|
87
109
|
case 'resolver':
|
|
88
110
|
this.#resolvers.set(specifier, {resolver: instance});
|
|
89
111
|
break;
|
|
90
|
-
case 'transformer':
|
|
91
|
-
this
|
|
92
|
-
|
|
112
|
+
case 'transformer': {
|
|
113
|
+
return this.initializeTransformer(instance, specifier);
|
|
114
|
+
}
|
|
93
115
|
}
|
|
94
116
|
},
|
|
95
117
|
);
|
|
@@ -98,53 +120,33 @@ export class AtlaspackWorker {
|
|
|
98
120
|
[RunResolverResolveOptions],
|
|
99
121
|
Promise<RunResolverResolveResult>
|
|
100
122
|
> = jsCallable(
|
|
101
|
-
async ({
|
|
102
|
-
key,
|
|
103
|
-
dependency: napiDependency,
|
|
104
|
-
specifier,
|
|
105
|
-
pipeline,
|
|
106
|
-
pluginOptions,
|
|
107
|
-
}) => {
|
|
123
|
+
async ({key, dependency: napiDependency, specifier, pipeline}) => {
|
|
108
124
|
const state = this.#resolvers.get(key);
|
|
109
125
|
if (!state) {
|
|
110
126
|
throw new Error(`Resolver not found: ${key}`);
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
let packageManager = state.packageManager;
|
|
114
|
-
if (!packageManager) {
|
|
115
|
-
packageManager = new NodePackageManager(
|
|
116
|
-
this.#fs,
|
|
117
|
-
pluginOptions.projectRoot,
|
|
118
|
-
);
|
|
119
|
-
state.packageManager = packageManager;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
129
|
const env = new Environment(napiDependency.env);
|
|
123
130
|
const dependency = new Dependency(napiDependency, env);
|
|
124
131
|
|
|
125
132
|
const defaultOptions = {
|
|
126
133
|
logger: new PluginLogger(),
|
|
127
134
|
tracer: new PluginTracer(),
|
|
128
|
-
options: new PluginOptions(
|
|
129
|
-
...pluginOptions,
|
|
130
|
-
packageManager,
|
|
131
|
-
shouldAutoInstall: false,
|
|
132
|
-
inputFS: this.#fs,
|
|
133
|
-
outputFS: this.#fs,
|
|
134
|
-
}),
|
|
135
|
+
options: new PluginOptions(this.options),
|
|
135
136
|
} as const;
|
|
136
137
|
|
|
137
138
|
if (!('config' in state)) {
|
|
138
139
|
// @ts-expect-error TS2345
|
|
139
140
|
state.config = await state.resolver.loadConfig?.({
|
|
140
|
-
config: new PluginConfig(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
141
|
+
config: new PluginConfig(
|
|
142
|
+
{
|
|
143
|
+
env: napiDependency.env,
|
|
144
|
+
plugin: key,
|
|
145
|
+
isSource: true,
|
|
146
|
+
searchPath: 'index',
|
|
147
|
+
},
|
|
148
|
+
this.options,
|
|
149
|
+
),
|
|
148
150
|
...defaultOptions,
|
|
149
151
|
});
|
|
150
152
|
}
|
|
@@ -192,155 +194,248 @@ export class AtlaspackWorker {
|
|
|
192
194
|
runTransformerTransform: JsCallable<
|
|
193
195
|
[RunTransformerTransformOptions, Buffer, string | null | undefined],
|
|
194
196
|
Promise<RunTransformerTransformResult>
|
|
195
|
-
> = jsCallable(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
197
|
+
> = jsCallable(async ({key, asset: innerAsset}, contents, map) => {
|
|
198
|
+
const instance = this.#transformers.get(key);
|
|
199
|
+
if (!instance) {
|
|
200
|
+
throw new Error(`Transformer not found: ${key}`);
|
|
201
|
+
}
|
|
201
202
|
|
|
202
|
-
|
|
203
|
-
if (!packageManager) {
|
|
204
|
-
packageManager = new NodePackageManager(this.#fs, options.projectRoot);
|
|
205
|
-
state.packageManager = packageManager;
|
|
206
|
-
}
|
|
203
|
+
let {transformer, config, allowedEnv = new Set()} = instance;
|
|
207
204
|
|
|
208
|
-
|
|
209
|
-
const resolveFunc = (from: string, to: string): Promise<any> => {
|
|
210
|
-
let customRequire = module.createRequire(from);
|
|
211
|
-
let resolvedPath = customRequire.resolve(to);
|
|
205
|
+
let cacheBailouts = [];
|
|
212
206
|
|
|
213
|
-
|
|
214
|
-
|
|
207
|
+
const resolveFunc = (from: string, to: string): Promise<any> => {
|
|
208
|
+
let customRequire = module.createRequire(from);
|
|
209
|
+
let resolvedPath = customRequire.resolve(to);
|
|
210
|
+
// Tranformer not cacheable due to use of the resolve function
|
|
215
211
|
|
|
216
|
-
|
|
217
|
-
const mutableAsset = new MutableAsset(
|
|
218
|
-
innerAsset,
|
|
219
|
-
// @ts-expect-error TS2345
|
|
220
|
-
contents,
|
|
221
|
-
env,
|
|
222
|
-
this.#fs,
|
|
223
|
-
map,
|
|
224
|
-
options.projectRoot,
|
|
225
|
-
);
|
|
212
|
+
cacheBailouts.push(`resolve(${from}, ${to})`);
|
|
226
213
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
tracer: new PluginTracer(),
|
|
230
|
-
options: new PluginOptions({
|
|
231
|
-
...options,
|
|
232
|
-
packageManager,
|
|
233
|
-
shouldAutoInstall: false,
|
|
234
|
-
inputFS: this.#fs,
|
|
235
|
-
outputFS: this.#fs,
|
|
236
|
-
}),
|
|
237
|
-
} as const;
|
|
214
|
+
return Promise.resolve(resolvedPath);
|
|
215
|
+
};
|
|
238
216
|
|
|
217
|
+
const env = new Environment(innerAsset.env);
|
|
218
|
+
let mutableAsset = new MutableAsset(
|
|
219
|
+
innerAsset,
|
|
239
220
|
// @ts-expect-error TS2345
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
221
|
+
contents,
|
|
222
|
+
env,
|
|
223
|
+
this.#fs,
|
|
224
|
+
map,
|
|
225
|
+
this.options.projectRoot,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const pluginOptions = new PluginOptions(this.options);
|
|
229
|
+
const defaultOptions = {
|
|
230
|
+
logger: new PluginLogger(),
|
|
231
|
+
tracer: new PluginTracer(),
|
|
232
|
+
options: pluginOptions,
|
|
233
|
+
} as const;
|
|
234
|
+
|
|
235
|
+
if (transformer.loadConfig) {
|
|
236
|
+
if (config != null) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`Transformer (${key}) should not implement 'setup' and 'loadConfig'`,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
// @ts-expect-error TS2345
|
|
242
|
+
config = await transformer.loadConfig({
|
|
243
|
+
config: new PluginConfig(
|
|
244
|
+
{
|
|
245
|
+
plugin: key,
|
|
246
|
+
isSource: innerAsset.isSource,
|
|
247
|
+
searchPath: innerAsset.filePath,
|
|
248
|
+
env,
|
|
249
|
+
},
|
|
250
|
+
this.options,
|
|
251
|
+
),
|
|
249
252
|
...defaultOptions,
|
|
250
253
|
});
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
config,
|
|
257
|
-
resolve: resolveFunc,
|
|
258
|
-
...defaultOptions,
|
|
259
|
-
});
|
|
260
|
-
if (ast) {
|
|
261
|
-
mutableAsset.setAST(ast);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
255
|
+
// Transformer uses the deprecated loadConfig API, so mark as not
|
|
256
|
+
// cachable
|
|
257
|
+
cacheBailouts.push(`Transformer.loadConfig`);
|
|
258
|
+
}
|
|
264
259
|
|
|
265
|
-
|
|
260
|
+
if (transformer.parse) {
|
|
261
|
+
const ast = await transformer.parse({
|
|
266
262
|
// @ts-expect-error TS2322
|
|
267
263
|
asset: mutableAsset,
|
|
268
264
|
config,
|
|
269
265
|
resolve: resolveFunc,
|
|
270
266
|
...defaultOptions,
|
|
271
267
|
});
|
|
268
|
+
if (ast) {
|
|
269
|
+
mutableAsset.setAST(ast);
|
|
270
|
+
}
|
|
271
|
+
cacheBailouts.push(`Transformer.parse`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const [result, sideEffects] =
|
|
275
|
+
await this.#sideEffectDetector.monitorSideEffects(key, () =>
|
|
276
|
+
transformer.transform({
|
|
277
|
+
// @ts-expect-error TS2322
|
|
278
|
+
asset: mutableAsset,
|
|
279
|
+
config,
|
|
280
|
+
resolve: resolveFunc,
|
|
281
|
+
...defaultOptions,
|
|
282
|
+
}),
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
if (sideEffects.envUsage.didEnumerate) {
|
|
286
|
+
cacheBailouts.push(`Env access: enumeration of process.env`);
|
|
287
|
+
}
|
|
272
288
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
289
|
+
for (let variable of sideEffects.envUsage.vars) {
|
|
290
|
+
if (variable in allowedEnv) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
cacheBailouts.push(`Env access: ${variable}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for (let {method, path} of sideEffects.fsUsage) {
|
|
298
|
+
cacheBailouts.push(`FS usage: ${method}(${path})`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
assert(
|
|
302
|
+
result.length === 1,
|
|
303
|
+
'[V3] Unimplemented: Multiple asset return from Node transformer',
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
assert(
|
|
307
|
+
result[0] === mutableAsset,
|
|
308
|
+
'[V3] Unimplemented: New asset returned from Node transformer',
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (transformer.generate) {
|
|
312
|
+
const ast = await mutableAsset.getAST();
|
|
313
|
+
if (ast) {
|
|
314
|
+
const output = await transformer.generate({
|
|
315
|
+
// @ts-expect-error TS2322
|
|
316
|
+
asset: mutableAsset,
|
|
317
|
+
ast,
|
|
318
|
+
...defaultOptions,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
if (typeof output.content === 'string') {
|
|
322
|
+
mutableAsset.setCode(output.content);
|
|
323
|
+
} else if (output.content instanceof Buffer) {
|
|
324
|
+
mutableAsset.setBuffer(output.content);
|
|
325
|
+
} else {
|
|
326
|
+
// @ts-expect-error TS2345
|
|
327
|
+
mutableAsset.setStream(output.content);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (output.map) {
|
|
331
|
+
mutableAsset.setMap(output.map);
|
|
295
332
|
}
|
|
296
333
|
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
let assetBuffer: Buffer | null = await mutableAsset.getBuffer();
|
|
337
|
+
|
|
338
|
+
// If the asset has no code, we set the buffer to null, which we can
|
|
339
|
+
// detect in Rust, to avoid passing back an empty buffer, which we can't.
|
|
340
|
+
if (assetBuffer.length === 0) {
|
|
341
|
+
assetBuffer = null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (pluginOptions.used) {
|
|
345
|
+
// Plugin options accessed, so not cachable
|
|
346
|
+
cacheBailouts.push(`Plugin options accessed`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return [
|
|
350
|
+
{
|
|
351
|
+
id: mutableAsset.id,
|
|
352
|
+
bundleBehavior: bundleBehaviorMap.intoNullable(
|
|
353
|
+
mutableAsset.bundleBehavior,
|
|
354
|
+
),
|
|
355
|
+
code: [],
|
|
356
|
+
filePath: mutableAsset.filePath,
|
|
357
|
+
isBundleSplittable: mutableAsset.isBundleSplittable,
|
|
358
|
+
isSource: mutableAsset.isSource,
|
|
359
|
+
meta: mutableAsset.meta,
|
|
360
|
+
pipeline: mutableAsset.pipeline,
|
|
361
|
+
// Query should be undefined if it's empty
|
|
362
|
+
query: mutableAsset.query.toString() || undefined,
|
|
363
|
+
sideEffects: mutableAsset.sideEffects,
|
|
364
|
+
symbols: mutableAsset.symbols.intoNapi(),
|
|
365
|
+
type: mutableAsset.type,
|
|
366
|
+
uniqueKey: mutableAsset.uniqueKey,
|
|
367
|
+
},
|
|
368
|
+
assetBuffer,
|
|
369
|
+
// Only send back the map if it has changed
|
|
370
|
+
mutableAsset.isMapDirty
|
|
371
|
+
? // @ts-expect-error TS2533
|
|
372
|
+
JSON.stringify((await mutableAsset.getMap()).toVLQ())
|
|
373
|
+
: '',
|
|
374
|
+
// Limit to first 10 bailouts
|
|
375
|
+
cacheBailouts.slice(0, 10),
|
|
376
|
+
];
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
get options() {
|
|
380
|
+
if (this.#options == null) {
|
|
381
|
+
throw new Error('Plugin options have not been initialized');
|
|
382
|
+
}
|
|
383
|
+
return this.#options;
|
|
384
|
+
}
|
|
297
385
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
386
|
+
async initializeTransformer(instance: Transformer<any>, specifier: string) {
|
|
387
|
+
let transformer = instance;
|
|
388
|
+
let setup, config, allowedEnv;
|
|
389
|
+
|
|
390
|
+
let packageManager = new NodePackageManager(
|
|
391
|
+
this.#fs,
|
|
392
|
+
this.options.projectRoot,
|
|
393
|
+
);
|
|
302
394
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
395
|
+
if (transformer.setup) {
|
|
396
|
+
let setupResult = await transformer.setup({
|
|
397
|
+
logger: new PluginLogger(),
|
|
398
|
+
options: new PluginOptions({
|
|
399
|
+
...this.options,
|
|
400
|
+
shouldAutoInstall: false,
|
|
401
|
+
inputFS: this.#fs,
|
|
402
|
+
outputFS: this.#fs,
|
|
403
|
+
packageManager,
|
|
404
|
+
}),
|
|
405
|
+
config: new PluginConfig(
|
|
406
|
+
{
|
|
407
|
+
plugin: specifier,
|
|
408
|
+
searchPath: 'index',
|
|
409
|
+
// Consider project setup config as source
|
|
410
|
+
isSource: true,
|
|
411
|
+
},
|
|
412
|
+
this.options,
|
|
413
|
+
),
|
|
414
|
+
});
|
|
415
|
+
config = setupResult?.config;
|
|
416
|
+
allowedEnv = Object.fromEntries(
|
|
417
|
+
setupResult?.env?.map((env) => [env, process.env[env]]) || [],
|
|
306
418
|
);
|
|
307
419
|
|
|
308
|
-
|
|
420
|
+
// Always add the following env vars to the cache key
|
|
421
|
+
allowedEnv['NODE_ENV'] = process.env['NODE_ENV'];
|
|
309
422
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
423
|
+
setup = {
|
|
424
|
+
conditions: setupResult?.conditions,
|
|
425
|
+
config,
|
|
426
|
+
env: allowedEnv,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
315
429
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
isSource: mutableAsset.isSource,
|
|
326
|
-
meta: mutableAsset.meta,
|
|
327
|
-
pipeline: mutableAsset.pipeline,
|
|
328
|
-
// Query should be undefined if it's empty
|
|
329
|
-
query: mutableAsset.query.toString() || undefined,
|
|
330
|
-
sideEffects: mutableAsset.sideEffects,
|
|
331
|
-
symbols: mutableAsset.symbols.intoNapi(),
|
|
332
|
-
type: mutableAsset.type,
|
|
333
|
-
uniqueKey: mutableAsset.uniqueKey,
|
|
334
|
-
},
|
|
335
|
-
assetBuffer,
|
|
336
|
-
// Only send back the map if it has changed
|
|
337
|
-
mutableAsset.isMapDirty
|
|
338
|
-
? // @ts-expect-error TS2533
|
|
339
|
-
JSON.stringify((await mutableAsset.getMap()).toVLQ())
|
|
340
|
-
: '',
|
|
341
|
-
];
|
|
342
|
-
},
|
|
343
|
-
);
|
|
430
|
+
this.#transformers.set(specifier, {
|
|
431
|
+
transformer,
|
|
432
|
+
config,
|
|
433
|
+
packageManager,
|
|
434
|
+
allowedEnv,
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
return setup;
|
|
438
|
+
}
|
|
344
439
|
}
|
|
345
440
|
|
|
346
441
|
// Create napi worker and send it back to main thread
|
|
@@ -348,27 +443,45 @@ const worker = new AtlaspackWorker();
|
|
|
348
443
|
const napiWorker = napi.newNodejsWorker(worker);
|
|
349
444
|
parentPort?.postMessage(napiWorker);
|
|
350
445
|
|
|
446
|
+
parentPort?.setMaxListeners(parentPort.getMaxListeners() + 1);
|
|
447
|
+
parentPort?.addListener('message', (message: unknown) => {
|
|
448
|
+
if (message === 'clearState') {
|
|
449
|
+
worker.clearState();
|
|
450
|
+
parentPort?.postMessage('stateCleared');
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
|
|
351
454
|
type ResolverState<T> = {
|
|
352
455
|
resolver: Resolver<T>;
|
|
353
456
|
config?: T;
|
|
354
457
|
packageManager?: NodePackageManager;
|
|
355
458
|
};
|
|
356
459
|
|
|
357
|
-
type TransformerState<
|
|
460
|
+
type TransformerState<ConfigType> = {
|
|
358
461
|
packageManager?: NodePackageManager;
|
|
359
|
-
transformer: Transformer<
|
|
462
|
+
transformer: Transformer<ConfigType>;
|
|
463
|
+
config?: ConfigType;
|
|
464
|
+
allowedEnv?: Record<string, string | undefined>;
|
|
360
465
|
};
|
|
361
466
|
|
|
362
467
|
type LoadPluginOptions = {
|
|
363
468
|
kind: 'resolver' | 'transformer';
|
|
364
469
|
specifier: string;
|
|
365
470
|
resolveFrom: string;
|
|
366
|
-
|
|
471
|
+
options: RpcPluginOptions;
|
|
367
472
|
};
|
|
368
473
|
|
|
369
474
|
type RpcPluginOptions = {
|
|
370
475
|
projectRoot: string;
|
|
371
476
|
mode: string;
|
|
477
|
+
featureFlags: FeatureFlags;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
type Options = RpcPluginOptions & {
|
|
481
|
+
inputFS: FileSystem;
|
|
482
|
+
outputFS: FileSystem;
|
|
483
|
+
packageManager: NodePackageManager;
|
|
484
|
+
shouldAutoInstall: boolean;
|
|
372
485
|
};
|
|
373
486
|
|
|
374
487
|
type RunResolverResolveOptions = {
|
|
@@ -377,7 +490,6 @@ type RunResolverResolveOptions = {
|
|
|
377
490
|
dependency: napi.Dependency;
|
|
378
491
|
specifier: FilePath;
|
|
379
492
|
pipeline: string | null | undefined;
|
|
380
|
-
pluginOptions: RpcPluginOptions;
|
|
381
493
|
};
|
|
382
494
|
|
|
383
495
|
type RunResolverResolveResult = {
|
|
@@ -406,10 +518,14 @@ type RunTransformerTransformOptions = {
|
|
|
406
518
|
key: string;
|
|
407
519
|
// @ts-expect-error TS2724
|
|
408
520
|
env: napi.Environment;
|
|
409
|
-
options: RpcPluginOptions;
|
|
410
521
|
// @ts-expect-error TS2694
|
|
411
522
|
asset: napi.Asset;
|
|
412
523
|
};
|
|
413
524
|
|
|
414
|
-
|
|
415
|
-
|
|
525
|
+
type RunTransformerTransformResult = [
|
|
526
|
+
// @ts-expect-error TS2694
|
|
527
|
+
napi.RpcAssetResult,
|
|
528
|
+
Buffer,
|
|
529
|
+
string,
|
|
530
|
+
boolean,
|
|
531
|
+
];
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
PluginTracer as IPluginTracer,
|
|
7
7
|
NamedBundle as INamedBundle,
|
|
8
8
|
BundleGraph as IBundleGraph,
|
|
9
|
+
TransformerSetup,
|
|
9
10
|
} from '@atlaspack/types';
|
|
10
11
|
import {readConfig, hashObject} from '@atlaspack/utils';
|
|
11
12
|
import type {
|
|
@@ -29,6 +30,13 @@ import {PluginTracer} from '@atlaspack/profiler';
|
|
|
29
30
|
import {requestTypes} from '../RequestTracker';
|
|
30
31
|
import {fromProjectPath, fromProjectPathRelative} from '../projectPath';
|
|
31
32
|
|
|
33
|
+
type Setup<T> = (arg1: {
|
|
34
|
+
config: IConfig;
|
|
35
|
+
options: IPluginOptions;
|
|
36
|
+
logger: IPluginLogger;
|
|
37
|
+
tracer: IPluginTracer;
|
|
38
|
+
}) => Async<TransformerSetup<T>>;
|
|
39
|
+
|
|
32
40
|
export type PluginWithLoadConfig = {
|
|
33
41
|
loadConfig?: (arg1: {
|
|
34
42
|
config: IConfig;
|
|
@@ -104,6 +112,37 @@ export async function loadPluginConfig<T extends PluginWithLoadConfig>(
|
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
|
|
115
|
+
export async function loadPluginSetup<T>(
|
|
116
|
+
pluginName: string,
|
|
117
|
+
setup: Setup<T>,
|
|
118
|
+
config: Config,
|
|
119
|
+
options: AtlaspackOptions,
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
try {
|
|
122
|
+
let result = await setup({
|
|
123
|
+
config: new PublicConfig(config, options),
|
|
124
|
+
options: new PluginOptions(
|
|
125
|
+
optionsProxy(options, (option) => {
|
|
126
|
+
config.invalidateOnOptionChange.add(option);
|
|
127
|
+
}),
|
|
128
|
+
),
|
|
129
|
+
logger: new PluginLogger({origin: pluginName}),
|
|
130
|
+
tracer: new PluginTracer({
|
|
131
|
+
origin: pluginName,
|
|
132
|
+
category: 'setup',
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
config.result = result.config;
|
|
137
|
+
} catch (e: any) {
|
|
138
|
+
throw new ThrowableDiagnostic({
|
|
139
|
+
diagnostic: errorToDiagnostic(e, {
|
|
140
|
+
origin: pluginName,
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
107
146
|
/**
|
|
108
147
|
* Return value at a given key path within an object.
|
|
109
148
|
*
|