@atlaspack/core 2.38.3-dev-862af7d26.0 → 2.38.4

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.
@@ -75,29 +75,6 @@ function createAssetGraphRequestRust(rustAtlaspack) {
75
75
  return getAssetGraph(serializedAssetGraph, (_prevResult = prevResult) === null || _prevResult === void 0 ? void 0 : _prevResult.assetGraph);
76
76
  });
77
77
  let changedAssetsPropagation = new Set(changedAssets.keys());
78
- // Skip symbol propagation for runtime assets - they have pre-computed symbol data
79
- if (input.skipSymbolProp) {
80
- _logger().default.verbose({
81
- origin: '@atlaspack/core',
82
- message: 'Skipping symbol propagation for runtime asset graph'
83
- });
84
- } else {
85
- let errors = (0, _SymbolPropagation.propagateSymbols)({
86
- options,
87
- assetGraph,
88
- changedAssetsPropagation,
89
- assetGroupsWithRemovedParents: new Set(),
90
- previousErrors: new Map() //this.previousSymbolPropagationErrors,
91
- });
92
- if (errors.size > 0) {
93
- // Just throw the first error. Since errors can bubble (e.g. reexporting a reexported symbol also fails),
94
- // determining which failing export is the root cause is nontrivial (because of circular dependencies).
95
- throw new (_diagnostic().default)({
96
- diagnostic: [...errors.values()][0]
97
- });
98
- }
99
- }
100
- await (0, _dumpGraphToGraphViz.default)(assetGraph, 'AssetGraphV3');
101
78
  let result = {
102
79
  assetGraph,
103
80
  assetRequests: [],
@@ -106,16 +83,55 @@ function createAssetGraphRequestRust(rustAtlaspack) {
106
83
  changedAssetsPropagation,
107
84
  previousSymbolPropagationErrors: undefined
108
85
  };
109
- let [_commitResult, commitError] = await commitPromise;
110
- if (commitError) {
111
- throw new (_diagnostic().default)({
112
- diagnostic: {
113
- message: 'Error committing asset graph in Rust: ' + commitError.message
86
+
87
+ // When v3AssetGraphSyncImprovements is enabled, wrap downstream steps
88
+ // in try/catch and store the result even on error. This prevents Rust/JS
89
+ // divergence when symbol propagation or commit_assets fails.
90
+ let storeResultOnError = (0, _featureFlags().getFeatureFlag)('v3AssetGraphSyncImprovements');
91
+ try {
92
+ // Skip symbol propagation for runtime assets - they have pre-computed symbol data
93
+ if (input.skipSymbolProp) {
94
+ _logger().default.verbose({
95
+ origin: '@atlaspack/core',
96
+ message: 'Skipping symbol propagation for runtime asset graph'
97
+ });
98
+ } else {
99
+ let errors = (0, _SymbolPropagation.propagateSymbols)({
100
+ options,
101
+ assetGraph,
102
+ changedAssetsPropagation,
103
+ assetGroupsWithRemovedParents: new Set(),
104
+ previousErrors: new Map() //this.previousSymbolPropagationErrors,
105
+ });
106
+ if (errors.size > 0) {
107
+ // Just throw the first error. Since errors can bubble (e.g. reexporting a reexported symbol also fails),
108
+ // determining which failing export is the root cause is nontrivial (because of circular dependencies).
109
+ throw new (_diagnostic().default)({
110
+ diagnostic: [...errors.values()][0]
111
+ });
114
112
  }
115
- });
113
+ }
114
+ await (0, _dumpGraphToGraphViz.default)(assetGraph, 'AssetGraphV3');
115
+ let [_commitResult, commitError] = await commitPromise;
116
+ if (commitError) {
117
+ throw new (_diagnostic().default)({
118
+ diagnostic: {
119
+ message: 'Error committing asset graph in Rust: ' + commitError.message
120
+ }
121
+ });
122
+ }
123
+ await runInput.api.storeResult(result);
124
+ runInput.api.invalidateOnBuild();
125
+ } catch (e) {
126
+ if (storeResultOnError) {
127
+ // Store the graph even on error to prevent Rust/JS divergence.
128
+ // The graph from getAssetGraph is structurally correct — only
129
+ // downstream processing (symbols, commit) failed.
130
+ await runInput.api.storeResult(result);
131
+ runInput.api.invalidateOnBuild();
132
+ }
133
+ throw e;
116
134
  }
117
- await runInput.api.storeResult(result);
118
- runInput.api.invalidateOnBuild();
119
135
  return result;
120
136
  },
121
137
  input
@@ -124,25 +140,48 @@ function createAssetGraphRequestRust(rustAtlaspack) {
124
140
  function getAssetGraph(serializedGraph, prevAssetGraph) {
125
141
  let graph;
126
142
  let reuseEdges = false;
143
+ let clonePrevGraph = (0, _featureFlags().getFeatureFlag)('v3AssetGraphSyncImprovements');
127
144
  if (prevAssetGraph && serializedGraph.safeToSkipBundling) {
128
- graph = new _AssetGraph.default({
129
- _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
130
- _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
131
- nodes: prevAssetGraph.nodes,
132
- rootNodeId: prevAssetGraph.rootNodeId,
133
- adjacencyList: prevAssetGraph.adjacencyList
134
- });
145
+ if (clonePrevGraph) {
146
+ graph = new _AssetGraph.default({
147
+ _contentKeyToNodeId: new Map(prevAssetGraph._contentKeyToNodeId),
148
+ _nodeIdToContentKey: new Map(prevAssetGraph._nodeIdToContentKey),
149
+ nodes: [...prevAssetGraph.nodes],
150
+ rootNodeId: prevAssetGraph.rootNodeId,
151
+ adjacencyList: prevAssetGraph.adjacencyList
152
+ });
153
+ } else {
154
+ graph = new _AssetGraph.default({
155
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
156
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
157
+ nodes: prevAssetGraph.nodes,
158
+ rootNodeId: prevAssetGraph.rootNodeId,
159
+ adjacencyList: prevAssetGraph.adjacencyList
160
+ });
161
+ }
135
162
  reuseEdges = true;
136
163
  } else if (prevAssetGraph && (serializedGraph.updates.length > 0 || serializedGraph.nodes.length > 0)) {
137
- graph = new _AssetGraph.default({
138
- _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
139
- _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
140
- nodes: prevAssetGraph.nodes,
141
- initialCapacity: serializedGraph.edges.length,
142
- // Accomodate the root node
143
- initialNodeCapacity: prevAssetGraph.nodes.length + 1,
144
- rootNodeId: prevAssetGraph.rootNodeId
145
- });
164
+ if (clonePrevGraph) {
165
+ graph = new _AssetGraph.default({
166
+ _contentKeyToNodeId: new Map(prevAssetGraph._contentKeyToNodeId),
167
+ _nodeIdToContentKey: new Map(prevAssetGraph._nodeIdToContentKey),
168
+ nodes: [...prevAssetGraph.nodes],
169
+ initialCapacity: serializedGraph.edges.length,
170
+ // Accomodate the root node
171
+ initialNodeCapacity: prevAssetGraph.nodes.length + 1,
172
+ rootNodeId: prevAssetGraph.rootNodeId
173
+ });
174
+ } else {
175
+ graph = new _AssetGraph.default({
176
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
177
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
178
+ nodes: prevAssetGraph.nodes,
179
+ initialCapacity: serializedGraph.edges.length,
180
+ // Accomodate the root node
181
+ initialNodeCapacity: prevAssetGraph.nodes.length + 1,
182
+ rootNodeId: prevAssetGraph.rootNodeId
183
+ });
184
+ }
146
185
  graph.safeToIncrementallyBundle = false;
147
186
  } else {
148
187
  graph = new _AssetGraph.default({
@@ -220,33 +259,83 @@ function getAssetGraph(serializedGraph, prevAssetGraph) {
220
259
  }
221
260
  return base;
222
261
  }
262
+ function buildDivergenceDiagnostics(divergenceType, newNode, existingNode, index) {
263
+ return {
264
+ contentKey: newNode.id,
265
+ divergenceType,
266
+ newNode: describeNode(newNode),
267
+ existingNode: existingNode ? describeNode(existingNode) : null,
268
+ iterationIndex: index,
269
+ totalSerializedNodes: nodesCount,
270
+ newNodesCount: serializedGraph.nodes.length,
271
+ updatesCount: serializedGraph.updates.length,
272
+ edgesCount: serializedGraph.edges.length,
273
+ hadPreviousGraph: !!prevAssetGraph,
274
+ safeToSkipBundling: serializedGraph.safeToSkipBundling,
275
+ graphNodeCount: graph._contentKeyToNodeId.size
276
+ };
277
+ }
223
278
  function updateNode(newNode, isUpdateNode, index) {
279
+ let healDivergence = (0, _featureFlags().getFeatureFlag)('v3AssetGraphSyncImprovements');
224
280
  if (isUpdateNode) {
225
281
  let existingNode = graph.getNodeByContentKey(newNode.id);
226
- (0, _assert().default)(existingNode && existingNode.type === newNode.type);
227
- Object.assign(existingNode, newNode);
282
+ if (healDivergence) {
283
+ if (existingNode) {
284
+ (0, _assert().default)(existingNode.type === newNode.type);
285
+ Object.assign(existingNode, newNode);
286
+ } else {
287
+ // Rust sent an update for a node JS doesn't have.
288
+ // This means JS's graph is stale. Add the node as new instead.
289
+ // This handles the "undefined == true" error class.
290
+ let diagnostics = buildDivergenceDiagnostics('update_node_not_found', newNode, existingNode, index);
291
+ _logger().default.warn({
292
+ origin: '@atlaspack/core',
293
+ message: `Rust/JS asset graph divergence healed: update node not found, ` + `adding as new. contentKey=${newNode.id} type=${newNode.type} iterationIndex=${index}`,
294
+ meta: {
295
+ trackableEvent: 'asset_graph_divergence_healed',
296
+ ...diagnostics
297
+ }
298
+ });
299
+ graph.addNodeByContentKey(newNode.id, newNode);
300
+ }
301
+ } else {
302
+ (0, _assert().default)(existingNode && existingNode.type === newNode.type);
303
+ Object.assign(existingNode, newNode);
304
+ }
228
305
  } else {
229
- try {
230
- graph.addNodeByContentKey(newNode.id, newNode);
231
- } catch (e) {
232
- if (e instanceof Error && e.message.includes('already has content key')) {
306
+ if (healDivergence) {
307
+ if (graph.hasContentKey(newNode.id)) {
308
+ // Rust sent a "new" node that JS already has.
309
+ // This means JS's graph has nodes that Rust considers new.
310
+ // Treat as an update instead of throwing.
311
+ // This handles the "Graph already has content key" error class.
233
312
  let existingNode = graph.getNodeByContentKey(newNode.id);
234
- let diagnostics = {
235
- contentKey: newNode.id,
236
- newNode: describeNode(newNode),
237
- existingNode: existingNode ? describeNode(existingNode) : null,
238
- iterationIndex: index,
239
- totalSerializedNodes: nodesCount,
240
- newNodesCount: serializedGraph.nodes.length,
241
- updatesCount: serializedGraph.updates.length,
242
- edgesCount: serializedGraph.edges.length,
243
- hadPreviousGraph: !!prevAssetGraph,
244
- safeToSkipBundling: serializedGraph.safeToSkipBundling,
245
- graphNodeCount: graph._contentKeyToNodeId.size
246
- };
247
- throw new Error(`Graph already has content key '${newNode.id}'. Diagnostics: ${JSON.stringify(diagnostics, null, 2)}`);
313
+ let diagnostics = buildDivergenceDiagnostics('new_node_already_exists', newNode, existingNode, index);
314
+ _logger().default.warn({
315
+ origin: '@atlaspack/core',
316
+ message: `Rust/JS asset graph divergence healed: new node already exists, ` + `treating as update. contentKey=${newNode.id} type=${newNode.type} iterationIndex=${index}`,
317
+ meta: {
318
+ trackableEvent: 'asset_graph_divergence_healed',
319
+ ...diagnostics
320
+ }
321
+ });
322
+ if (existingNode) {
323
+ Object.assign(existingNode, newNode);
324
+ }
325
+ } else {
326
+ graph.addNodeByContentKey(newNode.id, newNode);
327
+ }
328
+ } else {
329
+ try {
330
+ graph.addNodeByContentKey(newNode.id, newNode);
331
+ } catch (e) {
332
+ if (e instanceof Error && e.message.includes('already has content key')) {
333
+ let existingNode = graph.getNodeByContentKey(newNode.id);
334
+ let diagnostics = buildDivergenceDiagnostics('new_node_already_exists', newNode, existingNode, index);
335
+ throw new Error(`Graph already has content key '${newNode.id}'. Diagnostics: ${JSON.stringify(diagnostics, null, 2)}`);
336
+ }
337
+ throw e;
248
338
  }
249
- throw e;
250
339
  }
251
340
  }
252
341
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.38.3-dev-862af7d26.0",
3
+ "version": "2.38.4",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,23 +22,23 @@
22
22
  "build:lib": "gulp build --gulpfile ../../../gulpfile.js --cwd ."
23
23
  },
24
24
  "dependencies": {
25
- "@atlaspack/build-cache": "2.13.15-dev-862af7d26.0",
26
- "@atlaspack/cache": "3.2.56-dev-862af7d26.0",
27
- "@atlaspack/diagnostic": "2.14.5-dev-862af7d26.0",
28
- "@atlaspack/events": "2.14.5-dev-862af7d26.0",
29
- "@atlaspack/feature-flags": "2.31.1-dev-862af7d26.0",
30
- "@atlaspack/fs": "2.15.56-dev-862af7d26.0",
31
- "@atlaspack/graph": "3.6.23-dev-862af7d26.0",
32
- "@atlaspack/logger": "2.14.53-dev-862af7d26.0",
33
- "@atlaspack/package-manager": "2.14.61-dev-862af7d26.0",
34
- "@atlaspack/plugin": "2.14.61-dev-862af7d26.0",
35
- "@atlaspack/profiler": "2.15.22-dev-862af7d26.0",
36
- "@atlaspack/rust": "3.28.1-dev-862af7d26.0",
37
- "@atlaspack/source-map": "3.3.5-dev-862af7d26.0",
38
- "@atlaspack/types": "2.15.51-dev-862af7d26.0",
39
- "@atlaspack/utils": "3.4.3-dev-862af7d26.0",
40
- "@atlaspack/workers": "2.14.61-dev-862af7d26.0",
41
25
  "@mischnic/json-sourcemap": "^0.1.0",
26
+ "@atlaspack/build-cache": "2.13.16",
27
+ "@atlaspack/cache": "3.2.57",
28
+ "@atlaspack/diagnostic": "2.14.4",
29
+ "@atlaspack/events": "2.14.4",
30
+ "@atlaspack/feature-flags": "2.31.2",
31
+ "@atlaspack/fs": "2.15.57",
32
+ "@atlaspack/graph": "3.6.24",
33
+ "@atlaspack/logger": "2.14.54",
34
+ "@atlaspack/package-manager": "2.14.62",
35
+ "@atlaspack/plugin": "2.14.62",
36
+ "@atlaspack/profiler": "2.15.23",
37
+ "@atlaspack/rust": "3.29.1",
38
+ "@atlaspack/types": "2.15.52",
39
+ "@atlaspack/utils": "3.4.4",
40
+ "@atlaspack/workers": "2.14.62",
41
+ "@atlaspack/source-map": "3.3.6",
42
42
  "base-x": "^3.0.8",
43
43
  "browserslist": "^4.6.6",
44
44
  "clone": "^2.1.1",
@@ -50,16 +50,15 @@
50
50
  "semver": "^7.5.2"
51
51
  },
52
52
  "devDependencies": {
53
- "@atlaspack/babel-register": "2.14.5-dev-862af7d26.0",
53
+ "@atlaspack/babel-register": "2.14.5",
54
54
  "@types/node": ">= 18",
55
- "graphviz": "^0.0.9",
56
- "jest-diff": "*",
57
55
  "rfdc": "1",
56
+ "jest-diff": "*",
57
+ "graphviz": "^0.0.9",
58
58
  "tempy": "^0.2.1"
59
59
  },
60
60
  "browser": {
61
61
  "./src/serializerCore.js": "./src/serializerCore.browser.js"
62
62
  },
63
- "type": "commonjs",
64
- "gitHead": "862af7d26148df894cc5217b53d6cfac1bdc1026"
63
+ "type": "commonjs"
65
64
  }
@@ -335,7 +335,9 @@ export default class BundleGraph {
335
335
  ([, t]: [any, any]) => new Set([...t.values()]).size === t.size,
336
336
  )
337
337
  ) {
338
- let isReexportAll = nodeValueSymbols.get('*')?.local === '*';
338
+ let isReexportAll =
339
+ nodeValueSymbols.get('*')?.local === '*' ||
340
+ node.value.meta?.hasExportStar;
339
341
  let reexportAllLoc = isReexportAll
340
342
  ? nullthrows(nodeValueSymbols.get('*')).loc
341
343
  : undefined;
@@ -2317,7 +2319,7 @@ export default class BundleGraph {
2317
2319
  // Wildcard reexports are never listed in the reexporting asset's symbols.
2318
2320
  if (
2319
2321
  identifier == null &&
2320
- depSymbols.get('*')?.local === '*' &&
2322
+ (depSymbols.get('*')?.local === '*' || dep.meta?.hasExportStar) &&
2321
2323
  symbol !== 'default'
2322
2324
  ) {
2323
2325
  let resolved = this.getResolvedAsset(dep, boundary);
@@ -2455,7 +2457,7 @@ export default class BundleGraph {
2455
2457
  let depSymbols = dep.symbols;
2456
2458
  if (!depSymbols) continue;
2457
2459
 
2458
- if (depSymbols.get('*')?.local === '*') {
2460
+ if (depSymbols.get('*')?.local === '*' || dep.meta?.hasExportStar) {
2459
2461
  let resolved = this.getResolvedAsset(dep, boundary);
2460
2462
  if (!resolved) continue;
2461
2463
  let exported = this.getExportedSymbols(resolved, boundary)
@@ -1,7 +1,6 @@
1
1
  import type {ContentKey, NodeId} from '@atlaspack/graph';
2
2
  import type {Meta, Symbol} from '@atlaspack/types';
3
3
  import type {Diagnostic} from '@atlaspack/diagnostic';
4
- import {getFeatureFlag} from '@atlaspack/feature-flags';
5
4
  import type {
6
5
  AssetNode,
7
6
  DependencyNode,
@@ -95,7 +94,9 @@ export function propagateSymbols({
95
94
  }
96
95
  }
97
96
  let hasNamespaceOutgoingDeps = outgoingDeps.some(
98
- (d) => d.value.symbols?.get('*')?.local === '*',
97
+ (d) =>
98
+ d.value.symbols?.get('*')?.local === '*' ||
99
+ d.value.meta?.hasExportStar,
99
100
  );
100
101
 
101
102
  // 1) Determine what the incomingDeps requests from the asset
@@ -192,7 +193,10 @@ export function propagateSymbols({
192
193
  let depSymbols = dep.value.symbols;
193
194
  if (!depSymbols) continue;
194
195
 
195
- if (depSymbols.get('*')?.local === '*') {
196
+ if (
197
+ depSymbols.get('*')?.local === '*' ||
198
+ dep.value.meta?.hasExportStar
199
+ ) {
196
200
  if (addAll) {
197
201
  depUsedSymbolsDown.add('*');
198
202
  } else {
@@ -335,7 +339,10 @@ export function propagateSymbols({
335
339
  );
336
340
  }
337
341
 
338
- if (outgoingDepSymbols.get('*')?.local === '*') {
342
+ if (
343
+ outgoingDepSymbols.get('*')?.local === '*' ||
344
+ outgoingDep.value.meta?.hasExportStar
345
+ ) {
339
346
  outgoingDep.usedSymbolsUp.forEach((sResolved, s) => {
340
347
  if (s === 'default') {
341
348
  return;
@@ -453,7 +460,9 @@ export function propagateSymbols({
453
460
  let incomingDepSymbols = incomingDep.value.symbols;
454
461
  if (!incomingDepSymbols) continue;
455
462
 
456
- let hasNamespaceReexport = incomingDepSymbols.get('*')?.local === '*';
463
+ let hasNamespaceReexport =
464
+ incomingDepSymbols.get('*')?.local === '*' ||
465
+ incomingDep.value.meta?.hasExportStar;
457
466
  for (let s of incomingDep.usedSymbolsDown) {
458
467
  if (
459
468
  assetSymbols == null || // Assume everything could be provided if symbols are cleared