@atlaspack/core 2.38.3-dev-ce9f111cb.0 → 2.38.3
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 +24 -0
- package/dist/requests/AssetGraphRequestRust.js +169 -72
- package/lib/requests/AssetGraphRequestRust.js +157 -68
- package/package.json +21 -22
- package/src/requests/AssetGraphRequestRust.ts +195 -79
- package/tsconfig.tsbuildinfo +1 -1
- package/LICENSE +0 -201
|
@@ -82,31 +82,6 @@ export function createAssetGraphRequestRust(
|
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
let changedAssetsPropagation = new Set(changedAssets.keys());
|
|
85
|
-
// Skip symbol propagation for runtime assets - they have pre-computed symbol data
|
|
86
|
-
if (input.skipSymbolProp) {
|
|
87
|
-
logger.verbose({
|
|
88
|
-
origin: '@atlaspack/core',
|
|
89
|
-
message: 'Skipping symbol propagation for runtime asset graph',
|
|
90
|
-
});
|
|
91
|
-
} else {
|
|
92
|
-
let errors = propagateSymbols({
|
|
93
|
-
options,
|
|
94
|
-
assetGraph,
|
|
95
|
-
changedAssetsPropagation,
|
|
96
|
-
assetGroupsWithRemovedParents: new Set(),
|
|
97
|
-
previousErrors: new Map(), //this.previousSymbolPropagationErrors,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (errors.size > 0) {
|
|
101
|
-
// Just throw the first error. Since errors can bubble (e.g. reexporting a reexported symbol also fails),
|
|
102
|
-
// determining which failing export is the root cause is nontrivial (because of circular dependencies).
|
|
103
|
-
throw new ThrowableDiagnostic({
|
|
104
|
-
diagnostic: [...errors.values()][0],
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
await dumpGraphToGraphViz(assetGraph, 'AssetGraphV3');
|
|
110
85
|
|
|
111
86
|
let result = {
|
|
112
87
|
assetGraph,
|
|
@@ -117,19 +92,61 @@ export function createAssetGraphRequestRust(
|
|
|
117
92
|
previousSymbolPropagationErrors: undefined,
|
|
118
93
|
};
|
|
119
94
|
|
|
120
|
-
|
|
95
|
+
// When v3AssetGraphSyncImprovements is enabled, wrap downstream steps
|
|
96
|
+
// in try/catch and store the result even on error. This prevents Rust/JS
|
|
97
|
+
// divergence when symbol propagation or commit_assets fails.
|
|
98
|
+
let storeResultOnError = getFeatureFlag('v3AssetGraphSyncImprovements');
|
|
121
99
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
100
|
+
try {
|
|
101
|
+
// Skip symbol propagation for runtime assets - they have pre-computed symbol data
|
|
102
|
+
if (input.skipSymbolProp) {
|
|
103
|
+
logger.verbose({
|
|
104
|
+
origin: '@atlaspack/core',
|
|
105
|
+
message: 'Skipping symbol propagation for runtime asset graph',
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
let errors = propagateSymbols({
|
|
109
|
+
options,
|
|
110
|
+
assetGraph,
|
|
111
|
+
changedAssetsPropagation,
|
|
112
|
+
assetGroupsWithRemovedParents: new Set(),
|
|
113
|
+
previousErrors: new Map(), //this.previousSymbolPropagationErrors,
|
|
114
|
+
});
|
|
130
115
|
|
|
131
|
-
|
|
132
|
-
|
|
116
|
+
if (errors.size > 0) {
|
|
117
|
+
// Just throw the first error. Since errors can bubble (e.g. reexporting a reexported symbol also fails),
|
|
118
|
+
// determining which failing export is the root cause is nontrivial (because of circular dependencies).
|
|
119
|
+
throw new ThrowableDiagnostic({
|
|
120
|
+
diagnostic: [...errors.values()][0],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await dumpGraphToGraphViz(assetGraph, 'AssetGraphV3');
|
|
126
|
+
|
|
127
|
+
let [_commitResult, commitError] = await commitPromise;
|
|
128
|
+
|
|
129
|
+
if (commitError) {
|
|
130
|
+
throw new ThrowableDiagnostic({
|
|
131
|
+
diagnostic: {
|
|
132
|
+
message:
|
|
133
|
+
'Error committing asset graph in Rust: ' + commitError.message,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
await runInput.api.storeResult(result);
|
|
139
|
+
runInput.api.invalidateOnBuild();
|
|
140
|
+
} catch (e) {
|
|
141
|
+
if (storeResultOnError) {
|
|
142
|
+
// Store the graph even on error to prevent Rust/JS divergence.
|
|
143
|
+
// The graph from getAssetGraph is structurally correct — only
|
|
144
|
+
// downstream processing (symbols, commit) failed.
|
|
145
|
+
await runInput.api.storeResult(result);
|
|
146
|
+
runInput.api.invalidateOnBuild();
|
|
147
|
+
}
|
|
148
|
+
throw e;
|
|
149
|
+
}
|
|
133
150
|
|
|
134
151
|
return result;
|
|
135
152
|
},
|
|
@@ -148,28 +165,52 @@ export function getAssetGraph(
|
|
|
148
165
|
|
|
149
166
|
let reuseEdges = false;
|
|
150
167
|
|
|
168
|
+
let clonePrevGraph = getFeatureFlag('v3AssetGraphSyncImprovements');
|
|
169
|
+
|
|
151
170
|
if (prevAssetGraph && serializedGraph.safeToSkipBundling) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
171
|
+
if (clonePrevGraph) {
|
|
172
|
+
graph = new AssetGraph({
|
|
173
|
+
_contentKeyToNodeId: new Map(prevAssetGraph._contentKeyToNodeId),
|
|
174
|
+
_nodeIdToContentKey: new Map(prevAssetGraph._nodeIdToContentKey),
|
|
175
|
+
nodes: [...prevAssetGraph.nodes],
|
|
176
|
+
rootNodeId: prevAssetGraph.rootNodeId,
|
|
177
|
+
adjacencyList: prevAssetGraph.adjacencyList,
|
|
178
|
+
});
|
|
179
|
+
} else {
|
|
180
|
+
graph = new AssetGraph({
|
|
181
|
+
_contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
|
|
182
|
+
_nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
|
|
183
|
+
nodes: prevAssetGraph.nodes,
|
|
184
|
+
rootNodeId: prevAssetGraph.rootNodeId,
|
|
185
|
+
adjacencyList: prevAssetGraph.adjacencyList,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
159
188
|
reuseEdges = true;
|
|
160
189
|
} else if (
|
|
161
190
|
prevAssetGraph &&
|
|
162
191
|
(serializedGraph.updates.length > 0 || serializedGraph.nodes.length > 0)
|
|
163
192
|
) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
193
|
+
if (clonePrevGraph) {
|
|
194
|
+
graph = new AssetGraph({
|
|
195
|
+
_contentKeyToNodeId: new Map(prevAssetGraph._contentKeyToNodeId),
|
|
196
|
+
_nodeIdToContentKey: new Map(prevAssetGraph._nodeIdToContentKey),
|
|
197
|
+
nodes: [...prevAssetGraph.nodes],
|
|
198
|
+
initialCapacity: serializedGraph.edges.length,
|
|
199
|
+
// Accomodate the root node
|
|
200
|
+
initialNodeCapacity: prevAssetGraph.nodes.length + 1,
|
|
201
|
+
rootNodeId: prevAssetGraph.rootNodeId,
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
graph = new AssetGraph({
|
|
205
|
+
_contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
|
|
206
|
+
_nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
|
|
207
|
+
nodes: prevAssetGraph.nodes,
|
|
208
|
+
initialCapacity: serializedGraph.edges.length,
|
|
209
|
+
// Accomodate the root node
|
|
210
|
+
initialNodeCapacity: prevAssetGraph.nodes.length + 1,
|
|
211
|
+
rootNodeId: prevAssetGraph.rootNodeId,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
173
214
|
graph.safeToIncrementallyBundle = false;
|
|
174
215
|
} else {
|
|
175
216
|
graph = new AssetGraph({
|
|
@@ -263,45 +304,120 @@ export function getAssetGraph(
|
|
|
263
304
|
return base;
|
|
264
305
|
}
|
|
265
306
|
|
|
307
|
+
function buildDivergenceDiagnostics(
|
|
308
|
+
divergenceType: string,
|
|
309
|
+
newNode: AssetGraphNode,
|
|
310
|
+
existingNode: AssetGraphNode | null | undefined,
|
|
311
|
+
index: number,
|
|
312
|
+
) {
|
|
313
|
+
return {
|
|
314
|
+
contentKey: newNode.id,
|
|
315
|
+
divergenceType,
|
|
316
|
+
newNode: describeNode(newNode),
|
|
317
|
+
existingNode: existingNode ? describeNode(existingNode) : null,
|
|
318
|
+
iterationIndex: index,
|
|
319
|
+
totalSerializedNodes: nodesCount,
|
|
320
|
+
newNodesCount: serializedGraph.nodes.length,
|
|
321
|
+
updatesCount: serializedGraph.updates.length,
|
|
322
|
+
edgesCount: serializedGraph.edges.length,
|
|
323
|
+
hadPreviousGraph: !!prevAssetGraph,
|
|
324
|
+
safeToSkipBundling: serializedGraph.safeToSkipBundling,
|
|
325
|
+
graphNodeCount: graph._contentKeyToNodeId.size,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
266
329
|
function updateNode(
|
|
267
330
|
newNode: AssetGraphNode,
|
|
268
331
|
isUpdateNode: boolean,
|
|
269
332
|
index: number,
|
|
270
333
|
) {
|
|
334
|
+
let healDivergence = getFeatureFlag('v3AssetGraphSyncImprovements');
|
|
335
|
+
|
|
271
336
|
if (isUpdateNode) {
|
|
272
337
|
let existingNode = graph.getNodeByContentKey(newNode.id);
|
|
273
338
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
339
|
+
if (healDivergence) {
|
|
340
|
+
if (existingNode) {
|
|
341
|
+
assert(existingNode.type === newNode.type);
|
|
342
|
+
Object.assign(existingNode, newNode);
|
|
343
|
+
} else {
|
|
344
|
+
// Rust sent an update for a node JS doesn't have.
|
|
345
|
+
// This means JS's graph is stale. Add the node as new instead.
|
|
346
|
+
// This handles the "undefined == true" error class.
|
|
347
|
+
let diagnostics = buildDivergenceDiagnostics(
|
|
348
|
+
'update_node_not_found',
|
|
349
|
+
newNode,
|
|
350
|
+
existingNode,
|
|
351
|
+
index,
|
|
352
|
+
);
|
|
353
|
+
logger.warn({
|
|
354
|
+
origin: '@atlaspack/core',
|
|
355
|
+
message:
|
|
356
|
+
`Rust/JS asset graph divergence healed: update node not found, ` +
|
|
357
|
+
`adding as new. contentKey=${newNode.id} type=${newNode.type} iterationIndex=${index}`,
|
|
358
|
+
meta: {
|
|
359
|
+
trackableEvent: 'asset_graph_divergence_healed',
|
|
360
|
+
...diagnostics,
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
graph.addNodeByContentKey(newNode.id, newNode);
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
assert(existingNode && existingNode.type === newNode.type);
|
|
367
|
+
Object.assign(existingNode, newNode);
|
|
368
|
+
}
|
|
277
369
|
} else {
|
|
278
|
-
|
|
279
|
-
graph.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
) {
|
|
370
|
+
if (healDivergence) {
|
|
371
|
+
if (graph.hasContentKey(newNode.id)) {
|
|
372
|
+
// Rust sent a "new" node that JS already has.
|
|
373
|
+
// This means JS's graph has nodes that Rust considers new.
|
|
374
|
+
// Treat as an update instead of throwing.
|
|
375
|
+
// This handles the "Graph already has content key" error class.
|
|
285
376
|
let existingNode = graph.getNodeByContentKey(newNode.id);
|
|
286
|
-
let diagnostics =
|
|
287
|
-
|
|
288
|
-
newNode
|
|
289
|
-
existingNode
|
|
290
|
-
|
|
291
|
-
totalSerializedNodes: nodesCount,
|
|
292
|
-
newNodesCount: serializedGraph.nodes.length,
|
|
293
|
-
updatesCount: serializedGraph.updates.length,
|
|
294
|
-
edgesCount: serializedGraph.edges.length,
|
|
295
|
-
hadPreviousGraph: !!prevAssetGraph,
|
|
296
|
-
safeToSkipBundling: serializedGraph.safeToSkipBundling,
|
|
297
|
-
graphNodeCount: graph._contentKeyToNodeId.size,
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
throw new Error(
|
|
301
|
-
`Graph already has content key '${newNode.id}'. Diagnostics: ${JSON.stringify(diagnostics, null, 2)}`,
|
|
377
|
+
let diagnostics = buildDivergenceDiagnostics(
|
|
378
|
+
'new_node_already_exists',
|
|
379
|
+
newNode,
|
|
380
|
+
existingNode,
|
|
381
|
+
index,
|
|
302
382
|
);
|
|
383
|
+
logger.warn({
|
|
384
|
+
origin: '@atlaspack/core',
|
|
385
|
+
message:
|
|
386
|
+
`Rust/JS asset graph divergence healed: new node already exists, ` +
|
|
387
|
+
`treating as update. contentKey=${newNode.id} type=${newNode.type} iterationIndex=${index}`,
|
|
388
|
+
meta: {
|
|
389
|
+
trackableEvent: 'asset_graph_divergence_healed',
|
|
390
|
+
...diagnostics,
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
if (existingNode) {
|
|
394
|
+
Object.assign(existingNode, newNode);
|
|
395
|
+
}
|
|
396
|
+
} else {
|
|
397
|
+
graph.addNodeByContentKey(newNode.id, newNode);
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
try {
|
|
401
|
+
graph.addNodeByContentKey(newNode.id, newNode);
|
|
402
|
+
} catch (e) {
|
|
403
|
+
if (
|
|
404
|
+
e instanceof Error &&
|
|
405
|
+
e.message.includes('already has content key')
|
|
406
|
+
) {
|
|
407
|
+
let existingNode = graph.getNodeByContentKey(newNode.id);
|
|
408
|
+
let diagnostics = buildDivergenceDiagnostics(
|
|
409
|
+
'new_node_already_exists',
|
|
410
|
+
newNode,
|
|
411
|
+
existingNode,
|
|
412
|
+
index,
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
throw new Error(
|
|
416
|
+
`Graph already has content key '${newNode.id}'. Diagnostics: ${JSON.stringify(diagnostics, null, 2)}`,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
throw e;
|
|
303
420
|
}
|
|
304
|
-
throw e;
|
|
305
421
|
}
|
|
306
422
|
}
|
|
307
423
|
}
|