@atlaspack/core 2.12.1-dev.3401 → 2.12.1-dev.3443
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/lib/AssetGraph.js +1 -2
- package/lib/Atlaspack.js +25 -3
- package/lib/AtlaspackConfig.schema.js +10 -36
- package/lib/BundleGraph.js +59 -5
- package/lib/Dependency.js +46 -1
- package/lib/Environment.js +12 -2
- package/lib/PackagerRunner.js +3 -45
- package/lib/RequestTracker.js +112 -30
- package/lib/SymbolPropagation.js +1 -1
- package/lib/Transformation.js +1 -15
- package/lib/UncommittedAsset.js +4 -4
- package/lib/Validation.js +1 -13
- package/lib/applyRuntimes.js +96 -20
- package/lib/assetUtils.js +9 -3
- package/lib/atlaspack-v3/AtlaspackV3.js +6 -8
- package/lib/atlaspack-v3/fs.js +8 -1
- package/lib/atlaspack-v3/worker/compat.js +57 -0
- package/lib/atlaspack-v3/worker/worker.js +156 -1
- package/lib/public/BundleGraph.js +68 -0
- package/lib/requests/AssetGraphRequestRust.js +79 -12
- package/lib/requests/BundleGraphRequest.js +19 -0
- package/lib/requests/WriteBundleRequest.js +15 -15
- package/lib/requests/asset-graph-diff.js +128 -0
- package/lib/resolveOptions.js +15 -8
- package/lib/types.js +2 -1
- package/package.json +19 -17
- package/src/AssetGraph.js +1 -1
- package/src/Atlaspack.js +28 -6
- package/src/AtlaspackConfig.schema.js +13 -36
- package/src/BundleGraph.js +77 -1
- package/src/CommittedAsset.js +1 -1
- package/src/Dependency.js +50 -12
- package/src/Environment.js +13 -15
- package/src/PackagerRunner.js +5 -53
- package/src/RequestTracker.js +144 -38
- package/src/SymbolPropagation.js +5 -2
- package/src/Transformation.js +1 -9
- package/src/UncommittedAsset.js +6 -6
- package/src/Validation.js +1 -7
- package/src/applyRuntimes.js +86 -22
- package/src/assetUtils.js +12 -19
- package/src/atlaspack-v3/AtlaspackV3.js +8 -11
- package/src/atlaspack-v3/fs.js +8 -3
- package/src/atlaspack-v3/jsCallable.js +4 -0
- package/src/atlaspack-v3/worker/compat.js +82 -0
- package/src/atlaspack-v3/worker/worker.js +209 -2
- package/src/public/BundleGraph.js +106 -0
- package/src/requests/AssetGraphRequestRust.js +105 -17
- package/src/requests/BundleGraphRequest.js +18 -0
- package/src/requests/WriteBundleRequest.js +17 -23
- package/src/requests/asset-graph-diff.js +145 -0
- package/src/resolveOptions.js +12 -2
- package/src/types.js +10 -0
- package/test/AssetGraph.test.js +23 -9
- package/test/AtlaspackConfigRequest.test.js +0 -161
- package/test/BundleGraph.test.js +8 -3
- package/test/Dependency.test.js +21 -0
- package/test/Environment.test.js +16 -5
- package/test/InternalAsset.test.js +8 -2
- package/test/PublicAsset.test.js +6 -2
- package/test/PublicBundle.test.js +1 -0
- package/test/PublicMutableBundleGraph.test.js +9 -4
- package/test/RequestTracker.test.js +139 -2
- package/test/SymbolPropagation.test.js +1 -0
- package/test/TargetRequest.test.js +25 -25
- package/test/requests/WriteBundleRequest.test.js +132 -0
- package/lib/atlaspack-v3/plugins/Resolver.js +0 -12
- package/lib/atlaspack-v3/plugins/index.js +0 -16
- package/src/atlaspack-v3/plugins/Resolver.js +0 -9
- package/src/atlaspack-v3/plugins/index.js +0 -3
package/src/applyRuntimes.js
CHANGED
|
@@ -32,6 +32,7 @@ import createAssetGraphRequest from './requests/AssetGraphRequest';
|
|
|
32
32
|
import {createDevDependency, runDevDepRequest} from './requests/DevDepRequest';
|
|
33
33
|
import {toProjectPath, fromProjectPathRelative} from './projectPath';
|
|
34
34
|
import {tracer, PluginTracer} from '@atlaspack/profiler';
|
|
35
|
+
import {DefaultMap} from '@atlaspack/utils';
|
|
35
36
|
|
|
36
37
|
type RuntimeConnection = {|
|
|
37
38
|
bundle: InternalBundle,
|
|
@@ -60,6 +61,14 @@ function nameRuntimeBundle(
|
|
|
60
61
|
bundle.displayName = name.replace(hashReference, '[hash]');
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
/**
|
|
65
|
+
* The applyRuntimes function is responsible for generating all the runtimes
|
|
66
|
+
* (assets created during the build that don't actually exist on disk) and then
|
|
67
|
+
* linking them into the bundle graph.
|
|
68
|
+
*
|
|
69
|
+
* Introduction of manifest bundles: https://github.com/parcel-bundler/parcel/pull/8837
|
|
70
|
+
* Introduction of reverse topology: https://github.com/parcel-bundler/parcel/pull/8981
|
|
71
|
+
*/
|
|
63
72
|
export default async function applyRuntimes<TResult: RequestResult>({
|
|
64
73
|
bundleGraph,
|
|
65
74
|
config,
|
|
@@ -82,11 +91,20 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
82
91
|
configs: Map<string, Config>,
|
|
83
92
|
|}): Promise<Map<string, Asset>> {
|
|
84
93
|
let runtimes = await config.getRuntimes();
|
|
85
|
-
let connections: Array<RuntimeConnection> = [];
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Usually, the assets returned from a runtime will go in the same bundle. It is
|
|
97
|
+
* possible though, for a runtime to return an asset with a `parallel` priority,
|
|
98
|
+
* which allows it to be moved to a separate bundle. In practice, this is
|
|
99
|
+
* usually used to generate application manifest files.
|
|
100
|
+
*
|
|
101
|
+
* When adding a manifest bundle (a whole new separate bundle) during a runtime,
|
|
102
|
+
* it needs to be added to a bundle group which will be potentially referenced
|
|
103
|
+
* by another bundle group. To avoid trying to reference a manifest entry which
|
|
104
|
+
* hasn't been created yet, we process the bundles from the bottom up (topological
|
|
105
|
+
* order), so that children will always be available when parents try to reference
|
|
106
|
+
* them.
|
|
107
|
+
*/
|
|
90
108
|
let bundles = [];
|
|
91
109
|
bundleGraph.traverseBundles({
|
|
92
110
|
exit(bundle) {
|
|
@@ -94,6 +112,8 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
94
112
|
},
|
|
95
113
|
});
|
|
96
114
|
|
|
115
|
+
let connectionMap = new DefaultMap(() => []);
|
|
116
|
+
|
|
97
117
|
for (let bundle of bundles) {
|
|
98
118
|
for (let runtime of runtimes) {
|
|
99
119
|
let measurement;
|
|
@@ -146,6 +166,11 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
146
166
|
|
|
147
167
|
let connectionBundle = bundle;
|
|
148
168
|
|
|
169
|
+
/**
|
|
170
|
+
* If a runtime asset is marked with a priority of `parallel` this
|
|
171
|
+
* means we need to create a new bundle for the asset and add it to
|
|
172
|
+
* all the same bundle groups.
|
|
173
|
+
*/
|
|
149
174
|
if (priority === 'parallel' && !bundle.needsStableName) {
|
|
150
175
|
let bundleGroups =
|
|
151
176
|
bundleGraph.getBundleGroupsContainingBundle(bundle);
|
|
@@ -169,10 +194,12 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
169
194
|
}
|
|
170
195
|
bundleGraph.createBundleReference(bundle, connectionBundle);
|
|
171
196
|
|
|
197
|
+
// Ensure we name the bundle now as all other bundles have already
|
|
198
|
+
// been named as this point.
|
|
172
199
|
nameRuntimeBundle(connectionBundle, bundle);
|
|
173
200
|
}
|
|
174
201
|
|
|
175
|
-
|
|
202
|
+
connectionMap.get(connectionBundle).push({
|
|
176
203
|
bundle: connectionBundle,
|
|
177
204
|
assetGroup,
|
|
178
205
|
dependency,
|
|
@@ -192,8 +219,28 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
192
219
|
}
|
|
193
220
|
}
|
|
194
221
|
|
|
195
|
-
|
|
196
|
-
|
|
222
|
+
/**
|
|
223
|
+
* When merging the connections in to the bundle graph, the topological
|
|
224
|
+
* order can create module not found errors in some situations, often when HMR
|
|
225
|
+
* is enabled. To fix this, we put the connections into DFS order.
|
|
226
|
+
*
|
|
227
|
+
* Note: While DFS order seems to be the most reliable order to process the
|
|
228
|
+
* connections, this is likely due to it being close to the order that the bundles were
|
|
229
|
+
* inserted into the graph. There is a known issue where runtime assets marked
|
|
230
|
+
* as `isEntry` can create scenarios where there is no correct load order that
|
|
231
|
+
* won't error, as the entry runtime assets are added to many bundles in a
|
|
232
|
+
* single bundle group but their dependencies are not.
|
|
233
|
+
*
|
|
234
|
+
* This issue is almost exclusive to HMR scenarios as the two HMR runtime
|
|
235
|
+
* plugins (@atlaspack/runtime-browser-hmr and @atlaspack/runtime-react-refresh)
|
|
236
|
+
* are the only known cases where a runtime asset is marked as `isEntry`.
|
|
237
|
+
*/
|
|
238
|
+
let connections: Array<RuntimeConnection> = [];
|
|
239
|
+
bundleGraph.traverseBundles({
|
|
240
|
+
enter(bundle) {
|
|
241
|
+
connections.push(...connectionMap.get(bundle));
|
|
242
|
+
},
|
|
243
|
+
});
|
|
197
244
|
|
|
198
245
|
// Add dev deps for runtime plugins AFTER running them, to account for lazy require().
|
|
199
246
|
for (let runtime of runtimes) {
|
|
@@ -214,23 +261,31 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
214
261
|
await runDevDepRequest(api, devDepRequest);
|
|
215
262
|
}
|
|
216
263
|
|
|
264
|
+
// Create a new AssetGraph from the generated runtime assets which also runs
|
|
265
|
+
// transforms and resolves all dependencies.
|
|
217
266
|
let {assetGraph: runtimesAssetGraph, changedAssets} =
|
|
218
267
|
await reconcileNewRuntimes(api, connections, optionsRef);
|
|
219
268
|
|
|
220
|
-
|
|
269
|
+
// Convert the runtime AssetGraph into a BundleGraph, this includes assigning
|
|
270
|
+
// the assets their public ids
|
|
271
|
+
let runtimesBundleGraph = InternalBundleGraph.fromAssetGraph(
|
|
221
272
|
runtimesAssetGraph,
|
|
222
273
|
options.mode === 'production',
|
|
223
274
|
bundleGraph._publicIdByAssetId,
|
|
224
275
|
bundleGraph._assetPublicIds,
|
|
225
276
|
);
|
|
226
277
|
|
|
227
|
-
// Merge the runtimes graph into the main bundle graph.
|
|
228
|
-
bundleGraph.merge(
|
|
229
|
-
|
|
278
|
+
// Merge the runtimes bundle graph into the main bundle graph.
|
|
279
|
+
bundleGraph.merge(runtimesBundleGraph);
|
|
280
|
+
|
|
281
|
+
// Add the public id mappings from the runtumes bundlegraph to the main bundle graph
|
|
282
|
+
for (let [assetId, publicId] of runtimesBundleGraph._publicIdByAssetId) {
|
|
230
283
|
bundleGraph._publicIdByAssetId.set(assetId, publicId);
|
|
231
284
|
bundleGraph._assetPublicIds.add(publicId);
|
|
232
285
|
}
|
|
233
286
|
|
|
287
|
+
// Connect each of the generated runtime assets to bundles in the main bundle
|
|
288
|
+
// graph. This is like a mini-bundling algorithm for runtime assets.
|
|
234
289
|
for (let {bundle, assetGroup, dependency, isEntry} of connections) {
|
|
235
290
|
let assetGroupNode = nodeFromAssetGroup(assetGroup);
|
|
236
291
|
let assetGroupAssetNodeIds = runtimesAssetGraph.getNodeIdsConnectedFrom(
|
|
@@ -241,6 +296,8 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
241
296
|
let runtimeNode = nullthrows(runtimesAssetGraph.getNode(runtimeNodeId));
|
|
242
297
|
invariant(runtimeNode.type === 'asset');
|
|
243
298
|
|
|
299
|
+
// Find the asset that the runtime asset should be connected from by resolving
|
|
300
|
+
// it's dependency.
|
|
244
301
|
let resolution =
|
|
245
302
|
dependency &&
|
|
246
303
|
bundleGraph.getResolvedAsset(
|
|
@@ -248,20 +305,25 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
248
305
|
bundle,
|
|
249
306
|
);
|
|
250
307
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
308
|
+
// Walk all the dependencies of the runtime assets and check if they are
|
|
309
|
+
// already reachable from the bundle that the runtime asset is assigned to.
|
|
310
|
+
// If so, we add them to `duplicatedContentKeys` to be skipped when assigning
|
|
311
|
+
// assets to bundles.
|
|
312
|
+
let runtimesBundleGraphRuntimeNodeId =
|
|
313
|
+
runtimesBundleGraph._graph.getNodeIdByContentKey(runtimeNode.id);
|
|
254
314
|
let duplicatedContentKeys: Set<ContentKey> = new Set();
|
|
255
|
-
|
|
256
|
-
let node = nullthrows(
|
|
315
|
+
runtimesBundleGraph._graph.traverse((nodeId, _, actions) => {
|
|
316
|
+
let node = nullthrows(runtimesBundleGraph._graph.getNode(nodeId));
|
|
257
317
|
if (node.type !== 'dependency') {
|
|
258
318
|
return;
|
|
259
319
|
}
|
|
260
320
|
|
|
261
|
-
let assets =
|
|
321
|
+
let assets = runtimesBundleGraph._graph
|
|
262
322
|
.getNodeIdsConnectedFrom(nodeId)
|
|
263
323
|
.map(assetNodeId => {
|
|
264
|
-
let assetNode = nullthrows(
|
|
324
|
+
let assetNode = nullthrows(
|
|
325
|
+
runtimesBundleGraph._graph.getNode(assetNodeId),
|
|
326
|
+
);
|
|
265
327
|
invariant(assetNode.type === 'asset');
|
|
266
328
|
return assetNode.value;
|
|
267
329
|
});
|
|
@@ -275,15 +337,17 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
275
337
|
actions.skipChildren();
|
|
276
338
|
}
|
|
277
339
|
}
|
|
278
|
-
},
|
|
340
|
+
}, runtimesBundleGraphRuntimeNodeId);
|
|
279
341
|
|
|
280
342
|
let bundleNodeId = bundleGraph._graph.getNodeIdByContentKey(bundle.id);
|
|
281
343
|
let bundleGraphRuntimeNodeId = bundleGraph._graph.getNodeIdByContentKey(
|
|
282
344
|
runtimeNode.id,
|
|
283
345
|
); // the node id is not constant between graphs
|
|
284
346
|
|
|
285
|
-
|
|
286
|
-
|
|
347
|
+
// Assign the runtime assets and all of it's depepdencies to the bundle unless
|
|
348
|
+
// we have detected it as already being reachable from this bundle via `duplicatedContentKeys`.
|
|
349
|
+
runtimesBundleGraph._graph.traverse((nodeId, _, actions) => {
|
|
350
|
+
let node = nullthrows(runtimesBundleGraph._graph.getNode(nodeId));
|
|
287
351
|
if (node.type === 'asset' || node.type === 'dependency') {
|
|
288
352
|
if (duplicatedContentKeys.has(node.id)) {
|
|
289
353
|
actions.skipChildren();
|
|
@@ -299,7 +363,7 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
299
363
|
bundleGraphEdgeTypes.contains,
|
|
300
364
|
);
|
|
301
365
|
}
|
|
302
|
-
},
|
|
366
|
+
}, runtimesBundleGraphRuntimeNodeId);
|
|
303
367
|
|
|
304
368
|
if (isEntry) {
|
|
305
369
|
bundleGraph._graph.addEdge(bundleNodeId, bundleGraphRuntimeNodeId);
|
package/src/assetUtils.js
CHANGED
|
@@ -36,14 +36,14 @@ import {
|
|
|
36
36
|
fromProjectPath,
|
|
37
37
|
fromProjectPathRelative,
|
|
38
38
|
} from './projectPath';
|
|
39
|
-
import {hashString} from '@atlaspack/rust';
|
|
39
|
+
import {hashString, createAssetId as createAssetIdRust} from '@atlaspack/rust';
|
|
40
40
|
import {BundleBehavior as BundleBehaviorMap} from './types';
|
|
41
41
|
import {PluginTracer} from '@atlaspack/profiler';
|
|
42
42
|
|
|
43
|
-
type AssetOptions = {|
|
|
43
|
+
export type AssetOptions = {|
|
|
44
44
|
id?: string,
|
|
45
45
|
committed?: boolean,
|
|
46
|
-
|
|
46
|
+
code: string | void | null,
|
|
47
47
|
filePath: ProjectPath,
|
|
48
48
|
query?: ?string,
|
|
49
49
|
type: string,
|
|
@@ -69,22 +69,15 @@ type AssetOptions = {|
|
|
|
69
69
|
|};
|
|
70
70
|
|
|
71
71
|
export function createAssetIdFromOptions(options: AssetOptions): string {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
options.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
options.env.id +
|
|
82
|
-
uniqueKey +
|
|
83
|
-
':' +
|
|
84
|
-
(options.pipeline ?? '') +
|
|
85
|
-
':' +
|
|
86
|
-
(options.query ?? ''),
|
|
87
|
-
);
|
|
72
|
+
return createAssetIdRust({
|
|
73
|
+
env: options.env,
|
|
74
|
+
filePath: options.filePath,
|
|
75
|
+
code: options.code,
|
|
76
|
+
pipeline: options.pipeline,
|
|
77
|
+
query: options.query,
|
|
78
|
+
uniqueKey: options.uniqueKey,
|
|
79
|
+
fileType: options.type,
|
|
80
|
+
});
|
|
88
81
|
}
|
|
89
82
|
|
|
90
83
|
export function createAsset(
|
|
@@ -24,6 +24,14 @@ export class AtlaspackV3 {
|
|
|
24
24
|
threads,
|
|
25
25
|
...options
|
|
26
26
|
}: AtlaspackV3Options) {
|
|
27
|
+
options.logLevel = options.logLevel || 'error';
|
|
28
|
+
options.defaultTargetOptions = options.defaultTargetOptions || {};
|
|
29
|
+
// $FlowFixMe "engines" are readonly
|
|
30
|
+
options.defaultTargetOptions.engines = options.defaultTargetOptions
|
|
31
|
+
.engines || {
|
|
32
|
+
browsers: [],
|
|
33
|
+
};
|
|
34
|
+
|
|
27
35
|
this._internal = new AtlaspackNapi({
|
|
28
36
|
fs,
|
|
29
37
|
nodeWorkers,
|
|
@@ -33,17 +41,6 @@ export class AtlaspackV3 {
|
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
async build(): Promise<any> {
|
|
37
|
-
const [workers, registerWorker] = this.#createWorkers();
|
|
38
|
-
|
|
39
|
-
let result = await this._internal.build({
|
|
40
|
-
registerWorker,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
for (const worker of workers) worker.terminate();
|
|
44
|
-
return result;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
44
|
async buildAssetGraph(): Promise<any> {
|
|
48
45
|
const [workers, registerWorker] = this.#createWorkers();
|
|
49
46
|
|
package/src/atlaspack-v3/fs.js
CHANGED
|
@@ -15,9 +15,14 @@ export function toFileSystemV3(fs: ClassicFileSystem): FileSystem {
|
|
|
15
15
|
canonicalize: jsCallable((path: FilePath) => fs.realpathSync(path)),
|
|
16
16
|
createDirectory: jsCallable((path: FilePath) => fs.mkdirp(path)),
|
|
17
17
|
cwd: jsCallable(() => fs.cwd()),
|
|
18
|
-
readFile: jsCallable((path: string, encoding?: Encoding) =>
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
readFile: jsCallable((path: string, encoding?: Encoding) => {
|
|
19
|
+
if (!encoding) {
|
|
20
|
+
// $FlowFixMe
|
|
21
|
+
return [...fs.readFileSync(path)];
|
|
22
|
+
} else {
|
|
23
|
+
return fs.readFileSync(path, encoding);
|
|
24
|
+
}
|
|
25
|
+
}),
|
|
21
26
|
isFile: (path: string) => {
|
|
22
27
|
try {
|
|
23
28
|
return fs.statSync(path).isFile();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type {PluginOptions, BundleBehavior, AST} from '@atlaspack/types';
|
|
3
|
+
|
|
4
|
+
import Environment from '../../public/Environment';
|
|
5
|
+
import {
|
|
6
|
+
BundleBehaviorNames,
|
|
7
|
+
BundleBehavior as BundleBehaviorMap,
|
|
8
|
+
} from '../../types';
|
|
9
|
+
|
|
10
|
+
export type InnerAsset = {|
|
|
11
|
+
id: string,
|
|
12
|
+
filePath: string,
|
|
13
|
+
code: Array<number>,
|
|
14
|
+
type: string,
|
|
15
|
+
bundleBehavior: number | null,
|
|
16
|
+
env: any,
|
|
17
|
+
|};
|
|
18
|
+
|
|
19
|
+
export class AssetCompat {
|
|
20
|
+
_inner: InnerAsset;
|
|
21
|
+
_ast: ?AST;
|
|
22
|
+
// TODO: Type properly
|
|
23
|
+
_dependencies: Array<any>;
|
|
24
|
+
|
|
25
|
+
constructor(_inner: InnerAsset, options: PluginOptions) {
|
|
26
|
+
this._inner = _inner;
|
|
27
|
+
// $FlowFixMe This isn't correct to flow but is enough to satisfy the runtime checks
|
|
28
|
+
this.env = new Environment(_inner.env, options);
|
|
29
|
+
this._dependencies = [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get id(): string {
|
|
33
|
+
return this._inner.id;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get filePath(): string {
|
|
37
|
+
return this._inner.filePath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get type(): string {
|
|
41
|
+
return this._inner.type;
|
|
42
|
+
}
|
|
43
|
+
set type(value: string) {
|
|
44
|
+
this._inner.type = value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get bundleBehavior(): ?BundleBehavior {
|
|
48
|
+
let bundleBehavior = this._inner.bundleBehavior;
|
|
49
|
+
return bundleBehavior == null ? null : BundleBehaviorNames[bundleBehavior];
|
|
50
|
+
}
|
|
51
|
+
set bundleBehavior(bundleBehavior: ?BundleBehavior): void {
|
|
52
|
+
this._inner.bundleBehavior = bundleBehavior
|
|
53
|
+
? BundleBehaviorMap[bundleBehavior]
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getCode(): string {
|
|
58
|
+
return Buffer.from(this._inner.code).toString();
|
|
59
|
+
}
|
|
60
|
+
setCode(code: string) {
|
|
61
|
+
this._inner.code = Array.from(new TextEncoder().encode(code));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getAST(): ?AST {
|
|
65
|
+
return this._ast;
|
|
66
|
+
}
|
|
67
|
+
setAST(ast: AST) {
|
|
68
|
+
this._ast = ast;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
addDependency(): string {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'[V3] Unimplemented: Asset.addDependency not yet implemented',
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
addURLDependency(): string {
|
|
78
|
+
throw new Error(
|
|
79
|
+
'[V3] Unimplemented: Asset.addURLDependency not yet implemented',
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -1,14 +1,221 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import assert from 'assert';
|
|
2
3
|
import * as napi from '@atlaspack/rust';
|
|
4
|
+
import type {
|
|
5
|
+
Resolver,
|
|
6
|
+
Transformer,
|
|
7
|
+
PluginOptions,
|
|
8
|
+
Dependency,
|
|
9
|
+
FilePath,
|
|
10
|
+
} from '@atlaspack/types';
|
|
3
11
|
import {workerData} from 'worker_threads';
|
|
4
|
-
import
|
|
12
|
+
import * as module from 'module';
|
|
13
|
+
|
|
14
|
+
import {AssetCompat} from './compat';
|
|
15
|
+
import type {InnerAsset} from './compat';
|
|
16
|
+
import {jsCallable} from '../jsCallable';
|
|
17
|
+
import type {JsCallable} from '../jsCallable';
|
|
18
|
+
|
|
19
|
+
const CONFIG = Symbol.for('parcel-plugin-config');
|
|
5
20
|
|
|
6
21
|
export class AtlaspackWorker {
|
|
7
|
-
#resolvers: Map<string,
|
|
22
|
+
#resolvers: Map<string, Resolver<*>>;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
this.#resolvers = new Map();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
loadPlugin: JsCallable<[LoadPluginOptions], Promise<void>> = jsCallable(
|
|
29
|
+
async ({kind, specifier, resolveFrom}) => {
|
|
30
|
+
let customRequire = module.createRequire(resolveFrom);
|
|
31
|
+
let resolvedPath = customRequire.resolve(specifier);
|
|
32
|
+
// $FlowFixMe
|
|
33
|
+
let resolvedModule = await import(resolvedPath);
|
|
34
|
+
|
|
35
|
+
let instance = undefined;
|
|
36
|
+
if (resolvedModule.default && resolvedModule.default[CONFIG]) {
|
|
37
|
+
instance = resolvedModule.default[CONFIG];
|
|
38
|
+
} else if (
|
|
39
|
+
resolvedModule.default &&
|
|
40
|
+
resolvedModule.default.default[CONFIG]
|
|
41
|
+
) {
|
|
42
|
+
instance = resolvedModule.default.default[CONFIG];
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Plugin could not be resolved\n\t${kind}\n\t${resolveFrom}\n\t${specifier}`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch (kind) {
|
|
50
|
+
case 'resolver':
|
|
51
|
+
this.#resolvers.set(specifier, instance);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
runResolverResolve: JsCallable<
|
|
58
|
+
[RunResolverResolveOptions],
|
|
59
|
+
Promise<RunResolverResolveResult>,
|
|
60
|
+
> = jsCallable(async ({key, dependency, specifier}) => {
|
|
61
|
+
const resolver = this.#resolvers.get(key);
|
|
62
|
+
if (!resolver) {
|
|
63
|
+
throw new Error(`Resolver not found: ${key}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const result = await resolver.resolve({
|
|
67
|
+
specifier,
|
|
68
|
+
dependency,
|
|
69
|
+
get options() {
|
|
70
|
+
throw new Error('TODO: Resolver.resolve.options');
|
|
71
|
+
},
|
|
72
|
+
get logger() {
|
|
73
|
+
throw new Error('TODO: Resolver.resolve.logger');
|
|
74
|
+
},
|
|
75
|
+
get tracer() {
|
|
76
|
+
throw new Error('TODO: Resolver.resolve.tracer');
|
|
77
|
+
},
|
|
78
|
+
get pipeline() {
|
|
79
|
+
throw new Error('TODO: Resolver.resolve.pipeline');
|
|
80
|
+
},
|
|
81
|
+
get config() {
|
|
82
|
+
throw new Error('TODO: Resolver.resolve.config');
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!result) {
|
|
87
|
+
return {
|
|
88
|
+
invalidations: [],
|
|
89
|
+
resolution: {type: 'unresolved'},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
invalidations: [],
|
|
95
|
+
resolution: {
|
|
96
|
+
type: 'resolved',
|
|
97
|
+
filePath: result.filePath || '',
|
|
98
|
+
canDefer: result.canDefer || false,
|
|
99
|
+
sideEffects: result.sideEffects || false,
|
|
100
|
+
code: result.code || undefined,
|
|
101
|
+
meta: result.meta || undefined,
|
|
102
|
+
pipeline: result.pipeline || undefined,
|
|
103
|
+
priority: result.priority && PriorityMap[result.priority],
|
|
104
|
+
query: result.query && result.query.toString(),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
});
|
|
8
108
|
|
|
9
109
|
ping() {
|
|
10
110
|
// console.log('Hi');
|
|
11
111
|
}
|
|
112
|
+
|
|
113
|
+
async runTransformer({
|
|
114
|
+
resolveFrom,
|
|
115
|
+
specifier,
|
|
116
|
+
options,
|
|
117
|
+
asset,
|
|
118
|
+
}: {|
|
|
119
|
+
resolveFrom: string,
|
|
120
|
+
specifier: string,
|
|
121
|
+
options: PluginOptions,
|
|
122
|
+
asset: InnerAsset,
|
|
123
|
+
|}): any {
|
|
124
|
+
const customRequire = module.createRequire(resolveFrom);
|
|
125
|
+
const resolvedPath = customRequire.resolve(specifier);
|
|
126
|
+
// $FlowFixMe
|
|
127
|
+
const transformerModule = await import(resolvedPath);
|
|
128
|
+
const transformer: Transformer<*> =
|
|
129
|
+
transformerModule.default.default[CONFIG];
|
|
130
|
+
|
|
131
|
+
let assetCompat = new AssetCompat(asset, options);
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
if (transformer.parse) {
|
|
135
|
+
// $FlowFixMe
|
|
136
|
+
const ast = await transformer.parse({asset: assetCompat}); // missing "config"
|
|
137
|
+
// $FlowFixMe
|
|
138
|
+
assetCompat.setAST(ast);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// $FlowFixMe
|
|
142
|
+
const result = await transformer.transform({
|
|
143
|
+
// $FlowFixMe
|
|
144
|
+
asset: assetCompat,
|
|
145
|
+
options,
|
|
146
|
+
config: null,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (transformer.generate) {
|
|
150
|
+
// $FlowFixMe
|
|
151
|
+
let output = await transformer.generate({
|
|
152
|
+
// $FlowFixMe
|
|
153
|
+
asset: assetCompat,
|
|
154
|
+
// $FlowFixMe
|
|
155
|
+
ast: assetCompat.getAST(),
|
|
156
|
+
});
|
|
157
|
+
// $FlowFixMe
|
|
158
|
+
assetCompat.setCode(output.content);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
assert(
|
|
162
|
+
result.length === 1,
|
|
163
|
+
'[V3] Unimplemented: Multiple asset return from Node transformer',
|
|
164
|
+
);
|
|
165
|
+
assert(
|
|
166
|
+
result[0] === assetCompat,
|
|
167
|
+
'[V3] Unimplemented: New asset returned from Node transformer',
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
asset,
|
|
172
|
+
dependencies: assetCompat._dependencies,
|
|
173
|
+
};
|
|
174
|
+
} catch (e) {
|
|
175
|
+
// TODO: Improve error logging from JS plugins. Without this you currently
|
|
176
|
+
// only see the error message, no stack trace.
|
|
177
|
+
// eslint-disable-next-line no-console
|
|
178
|
+
console.error(e);
|
|
179
|
+
throw e;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
12
182
|
}
|
|
13
183
|
|
|
14
184
|
napi.registerWorker(workerData.tx_worker, new AtlaspackWorker());
|
|
185
|
+
|
|
186
|
+
type LoadPluginOptions = {|
|
|
187
|
+
kind: 'resolver',
|
|
188
|
+
specifier: string,
|
|
189
|
+
resolveFrom: string,
|
|
190
|
+
|};
|
|
191
|
+
|
|
192
|
+
type RunResolverResolveOptions = {|
|
|
193
|
+
key: string,
|
|
194
|
+
dependency: Dependency,
|
|
195
|
+
specifier: FilePath,
|
|
196
|
+
|};
|
|
197
|
+
|
|
198
|
+
type RunResolverResolveResult = {|
|
|
199
|
+
invalidations: Array<*>,
|
|
200
|
+
resolution:
|
|
201
|
+
| {|type: 'unresolved'|}
|
|
202
|
+
| {|type: 'excluded'|}
|
|
203
|
+
| {|
|
|
204
|
+
type: 'resolved',
|
|
205
|
+
canDefer: boolean,
|
|
206
|
+
filePath: string,
|
|
207
|
+
sideEffects: boolean,
|
|
208
|
+
code?: string,
|
|
209
|
+
meta?: mixed,
|
|
210
|
+
pipeline?: string,
|
|
211
|
+
priority?: number,
|
|
212
|
+
query?: string,
|
|
213
|
+
|},
|
|
214
|
+
|};
|
|
215
|
+
|
|
216
|
+
const PriorityMap = {
|
|
217
|
+
sync: 0,
|
|
218
|
+
parallel: 1,
|
|
219
|
+
lazy: 2,
|
|
220
|
+
conditional: 3,
|
|
221
|
+
};
|