@atlaspack/core 2.26.2 → 2.27.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.
@@ -5,11 +5,17 @@ import type {Async} from '@atlaspack/types';
5
5
  import {instrument} from '@atlaspack/logger';
6
6
  import {getFeatureFlag} from '@atlaspack/feature-flags';
7
7
 
8
- import AssetGraph, {nodeFromAssetGroup} from '../AssetGraph';
8
+ import AssetGraph from '../AssetGraph';
9
9
  import type {AtlaspackV3} from '../atlaspack-v3';
10
10
  import {requestTypes, StaticRunOpts} from '../RequestTracker';
11
11
  import {propagateSymbols} from '../SymbolPropagation';
12
- import type {Environment, Asset} from '../types';
12
+ import type {
13
+ Environment,
14
+ Asset,
15
+ AssetGraphNode,
16
+ AssetNode,
17
+ DependencyNode,
18
+ } from '../types';
13
19
 
14
20
  import type {
15
21
  AssetGraphRequestInput,
@@ -17,6 +23,8 @@ import type {
17
23
  } from './AssetGraphRequest';
18
24
  import {toEnvironmentRef} from '../EnvironmentManager';
19
25
  import {getEnvironmentHash} from '../Environment';
26
+ import dumpGraphToGraphViz from '../dumpGraphToGraphViz';
27
+ import assert from 'assert';
20
28
 
21
29
  type RunInput = {
22
30
  input: AssetGraphRequestInput;
@@ -29,6 +37,14 @@ type AssetGraphRequest = {
29
37
  input: AssetGraphRequestInput;
30
38
  };
31
39
 
40
+ type SerializedAssetGraphDelta = {
41
+ nodes: Array<any>;
42
+ edges: Array<string>;
43
+ updates: Array<any>;
44
+ safeToSkipBundling: boolean;
45
+ hadPreviousGraph: boolean;
46
+ };
47
+
32
48
  export function createAssetGraphRequestRust(
33
49
  rustAtlaspack: AtlaspackV3,
34
50
  ): (input: AssetGraphRequestInput) => AssetGraphRequest {
@@ -37,16 +53,29 @@ export function createAssetGraphRequestRust(
37
53
  id: input.name,
38
54
  run: async (input) => {
39
55
  let options = input.options;
40
- let serializedAssetGraph = await rustAtlaspack.buildAssetGraph();
56
+ let serializedAssetGraph =
57
+ (await rustAtlaspack.buildAssetGraph()) as SerializedAssetGraphDelta;
41
58
 
42
- // @ts-expect-error TS7006
59
+ // Newly created nodes
43
60
  serializedAssetGraph.nodes = serializedAssetGraph.nodes.map((node) =>
44
61
  JSON.parse(node),
45
62
  );
46
63
 
64
+ // Updated existing nodes
65
+ serializedAssetGraph.updates = serializedAssetGraph.updates.map((node) =>
66
+ JSON.parse(node),
67
+ );
68
+
69
+ // Don't reuse a previous asset graph result if Rust didn't have one too
70
+ let prevResult = null;
71
+ if (serializedAssetGraph.hadPreviousGraph) {
72
+ prevResult =
73
+ await input.api.getPreviousResult<AssetGraphRequestResult>();
74
+ }
75
+
47
76
  let {assetGraph, changedAssets} = instrument(
48
77
  'atlaspack_v3_getAssetGraph',
49
- () => getAssetGraph(serializedAssetGraph),
78
+ () => getAssetGraph(serializedAssetGraph, prevResult?.assetGraph),
50
79
  );
51
80
 
52
81
  let changedAssetsPropagation = new Set(changedAssets.keys());
@@ -66,30 +95,81 @@ export function createAssetGraphRequestRust(
66
95
  });
67
96
  }
68
97
 
69
- return {
98
+ await dumpGraphToGraphViz(assetGraph, 'AssetGraphV3');
99
+
100
+ let result = {
70
101
  assetGraph,
71
102
  assetRequests: [],
72
- assetGroupsWithRemovedParents: new Set(),
103
+ assetGroupsWithRemovedParents: new Set<number>(),
73
104
  changedAssets,
74
105
  changedAssetsPropagation,
75
106
  previousSymbolPropagationErrors: undefined,
76
107
  };
108
+
109
+ await input.api.storeResult(result);
110
+ input.api.invalidateOnBuild();
111
+
112
+ return result;
77
113
  },
78
114
  input,
79
115
  });
80
116
  }
81
117
 
82
- export function getAssetGraph(serializedGraph: any): {
118
+ export function getAssetGraph(
119
+ serializedGraph: any,
120
+ prevAssetGraph?: AssetGraph,
121
+ ): {
83
122
  assetGraph: AssetGraph;
84
123
  changedAssets: Map<string, Asset>;
85
124
  } {
86
- let graph = new AssetGraph({
87
- _contentKeyToNodeId: new Map(),
88
- _nodeIdToContentKey: new Map(),
89
- initialCapacity: serializedGraph.edges.length,
90
- });
125
+ let graph: AssetGraph;
126
+
127
+ let reuseEdges = false;
128
+
129
+ if (prevAssetGraph && serializedGraph.safeToSkipBundling) {
130
+ graph = new AssetGraph({
131
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
132
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
133
+ nodes: prevAssetGraph.nodes,
134
+ rootNodeId: prevAssetGraph.rootNodeId,
135
+ adjacencyList: prevAssetGraph.adjacencyList,
136
+ });
137
+ reuseEdges = true;
138
+ } else if (
139
+ prevAssetGraph &&
140
+ (serializedGraph.updates.length > 0 || serializedGraph.nodes.length > 0)
141
+ ) {
142
+ graph = new AssetGraph({
143
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
144
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
145
+ nodes: prevAssetGraph.nodes,
146
+ initialCapacity: serializedGraph.edges.length,
147
+ // Accomodate the root node
148
+ initialNodeCapacity: prevAssetGraph.nodes.length + 1,
149
+ rootNodeId: prevAssetGraph.rootNodeId,
150
+ });
151
+ graph.safeToIncrementallyBundle = false;
152
+ } else {
153
+ graph = new AssetGraph({
154
+ _contentKeyToNodeId: new Map(),
155
+ _nodeIdToContentKey: new Map(),
156
+ initialCapacity: serializedGraph.edges.length,
157
+ // Accomodate the root node
158
+ initialNodeCapacity: serializedGraph.nodes.length + 1,
159
+ });
160
+
161
+ let rootNodeId = graph.addNodeByContentKey('@@root', {
162
+ id: '@@root',
163
+ type: 'root',
164
+ value: null,
165
+ });
166
+
167
+ graph.setRootNodeId(rootNodeId);
168
+ graph.safeToIncrementallyBundle = false;
169
+ }
91
170
 
92
- graph.safeToIncrementallyBundle = false;
171
+ invariant(graph, 'Asset graph not initialized');
172
+ invariant(graph.rootNodeId != null, 'Asset graph has no root node');
93
173
 
94
174
  // @ts-expect-error TS7031
95
175
  function mapSymbols({exported, ...symbol}) {
@@ -133,23 +213,36 @@ export function getAssetGraph(serializedGraph: any): {
133
213
 
134
214
  let envId = envs.get(envKey);
135
215
  if (envId == null) {
136
- envId = `${envs.size}`;
216
+ envId = envs.size.toString();
137
217
  envs.set(envKey, envId);
138
218
  }
139
219
 
140
220
  return envId;
141
221
  };
142
222
 
143
- for (let node of serializedGraph.nodes) {
144
- if (node.type === 'root') {
145
- let index = graph.addNodeByContentKey('@@root', {
146
- id: '@@root',
147
- type: 'root',
148
- value: null,
149
- });
223
+ function updateNode(newNode: AssetGraphNode, isUpdateNode: boolean) {
224
+ if (isUpdateNode) {
225
+ let existingNode = graph.getNodeByContentKey(newNode.id);
226
+
227
+ assert(existingNode && existingNode.type === newNode.type);
150
228
 
151
- graph.setRootNodeId(index);
152
- } else if (node.type === 'entry') {
229
+ Object.assign(existingNode, newNode);
230
+ } else {
231
+ graph.addNodeByContentKey(newNode.id, newNode);
232
+ }
233
+ }
234
+
235
+ let nodeTypeSwitchoverIndex = serializedGraph.nodes.length;
236
+ let nodesCount =
237
+ serializedGraph.nodes.length + serializedGraph.updates.length;
238
+
239
+ for (let index = 0; index < nodesCount; index++) {
240
+ let isUpdateNode = index >= nodeTypeSwitchoverIndex;
241
+ let node = isUpdateNode
242
+ ? serializedGraph.updates[index - nodeTypeSwitchoverIndex]
243
+ : serializedGraph.nodes[index];
244
+
245
+ if (node.type === 'entry') {
153
246
  let id = 'entry:' + ++entry;
154
247
 
155
248
  graph.addNodeByContentKey(id, {
@@ -184,14 +277,15 @@ export function getAssetGraph(serializedGraph: any): {
184
277
 
185
278
  changedAssets.set(id, asset);
186
279
 
187
- graph.addNodeByContentKey(id, {
280
+ let assetNode: AssetNode = {
188
281
  id,
189
282
  type: 'asset',
190
283
  usedSymbols: new Set(),
191
284
  usedSymbolsDownDirty: true,
192
285
  usedSymbolsUpDirty: true,
193
286
  value: asset,
194
- });
287
+ };
288
+ updateNode(assetNode, isUpdateNode);
195
289
  } else if (node.type === 'dependency') {
196
290
  let {dependency, id} = node.value;
197
291
 
@@ -213,7 +307,7 @@ export function getAssetGraph(serializedGraph: any): {
213
307
  usedSymbolsUp.set('*', undefined);
214
308
  }
215
309
 
216
- graph.addNodeByContentKey(id, {
310
+ let depNode: DependencyNode = {
217
311
  id,
218
312
  type: 'dependency',
219
313
  deferred: false,
@@ -226,25 +320,29 @@ export function getAssetGraph(serializedGraph: any): {
226
320
  usedSymbolsUpDirtyDown: true,
227
321
  usedSymbolsUpDirtyUp: true,
228
322
  value: dependency,
229
- });
323
+ };
324
+
325
+ updateNode(depNode, isUpdateNode);
230
326
  }
231
327
  }
232
328
 
233
- for (let i = 0; i < serializedGraph.edges.length; i += 2) {
234
- let from = serializedGraph.edges[i];
235
- let to = serializedGraph.edges[i + 1];
236
- let fromNode = graph.getNode(from);
237
- let toNode = graph.getNode(to);
329
+ if (!reuseEdges) {
330
+ for (let i = 0; i < serializedGraph.edges.length; i += 2) {
331
+ let from = serializedGraph.edges[i];
332
+ let to = serializedGraph.edges[i + 1];
333
+ let fromNode = graph.getNode(from);
334
+ let toNode = graph.getNode(to);
238
335
 
239
- if (fromNode?.type === 'dependency') {
240
- invariant(toNode?.type === 'asset');
241
- }
336
+ if (fromNode?.type === 'dependency') {
337
+ invariant(toNode?.type === 'asset');
338
+ }
242
339
 
243
- if (fromNode?.type === 'asset' && toNode?.type === 'dependency') {
244
- fromNode.value.dependencies.set(toNode.value.id, toNode.value);
245
- }
340
+ if (fromNode?.type === 'asset' && toNode?.type === 'dependency') {
341
+ fromNode.value.dependencies.set(toNode.value.id, toNode.value);
342
+ }
246
343
 
247
- graph.addEdge(from, to);
344
+ graph.addEdge(from, to);
345
+ }
248
346
  }
249
347
 
250
348
  return {
@@ -198,29 +198,19 @@ export async function resolveAtlaspackConfig(
198
198
  await parseAndProcessConfig(configPath, contents, options);
199
199
 
200
200
  if (options.additionalReporters.length > 0) {
201
- if (options.featureFlags.deduplicateReporters) {
202
- const reporterMap = new Map<PackageName, AtlaspackPluginNode>();
201
+ const reporterMap = new Map<PackageName, AtlaspackPluginNode>();
203
202
 
204
- options.additionalReporters.forEach(({packageName, resolveFrom}) => {
205
- reporterMap.set(packageName, {packageName, resolveFrom});
206
- });
203
+ options.additionalReporters.forEach(({packageName, resolveFrom}) => {
204
+ reporterMap.set(packageName, {packageName, resolveFrom});
205
+ });
207
206
 
208
- config.reporters?.forEach((reporter) => {
209
- if (!reporterMap.has(reporter.packageName)) {
210
- reporterMap.set(reporter.packageName, reporter);
211
- }
212
- });
207
+ config.reporters?.forEach((reporter) => {
208
+ if (!reporterMap.has(reporter.packageName)) {
209
+ reporterMap.set(reporter.packageName, reporter);
210
+ }
211
+ });
213
212
 
214
- config.reporters = Array.from(reporterMap.values());
215
- } else {
216
- config.reporters = [
217
- ...options.additionalReporters.map(({packageName, resolveFrom}) => ({
218
- packageName,
219
- resolveFrom,
220
- })),
221
- ...(config.reporters ?? []),
222
- ];
223
- }
213
+ config.reporters = Array.from(reporterMap.values());
224
214
  }
225
215
 
226
216
  return {config, extendedFiles, usedDefault};
@@ -436,5 +436,6 @@ function getSerializedGraph() {
436
436
  },
437
437
  },
438
438
  ],
439
+ updates: [],
439
440
  };
440
441
  }