@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.
@@ -38,6 +38,7 @@ var _RequestTracker = require("../RequestTracker");
38
38
  var _SymbolPropagation = require("../SymbolPropagation");
39
39
  var _EnvironmentManager = require("../EnvironmentManager");
40
40
  var _Environment = require("../Environment");
41
+ var _dumpGraphToGraphViz = _interopRequireDefault(require("../dumpGraphToGraphViz"));
41
42
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42
43
  function createAssetGraphRequestRust(rustAtlaspack) {
43
44
  return input => ({
@@ -47,12 +48,24 @@ function createAssetGraphRequestRust(rustAtlaspack) {
47
48
  let options = input.options;
48
49
  let serializedAssetGraph = await rustAtlaspack.buildAssetGraph();
49
50
 
50
- // @ts-expect-error TS7006
51
+ // Newly created nodes
51
52
  serializedAssetGraph.nodes = serializedAssetGraph.nodes.map(node => JSON.parse(node));
53
+
54
+ // Updated existing nodes
55
+ serializedAssetGraph.updates = serializedAssetGraph.updates.map(node => JSON.parse(node));
56
+
57
+ // Don't reuse a previous asset graph result if Rust didn't have one too
58
+ let prevResult = null;
59
+ if (serializedAssetGraph.hadPreviousGraph) {
60
+ prevResult = await input.api.getPreviousResult();
61
+ }
52
62
  let {
53
63
  assetGraph,
54
64
  changedAssets
55
- } = (0, _logger().instrument)('atlaspack_v3_getAssetGraph', () => getAssetGraph(serializedAssetGraph));
65
+ } = (0, _logger().instrument)('atlaspack_v3_getAssetGraph', () => {
66
+ var _prevResult;
67
+ return getAssetGraph(serializedAssetGraph, (_prevResult = prevResult) === null || _prevResult === void 0 ? void 0 : _prevResult.assetGraph);
68
+ });
56
69
  let changedAssetsPropagation = new Set(changedAssets.keys());
57
70
  let errors = (0, _SymbolPropagation.propagateSymbols)({
58
71
  options,
@@ -69,7 +82,8 @@ function createAssetGraphRequestRust(rustAtlaspack) {
69
82
  diagnostic: [...errors.values()][0]
70
83
  });
71
84
  }
72
- return {
85
+ await (0, _dumpGraphToGraphViz.default)(assetGraph, 'AssetGraphV3');
86
+ let result = {
73
87
  assetGraph,
74
88
  assetRequests: [],
75
89
  assetGroupsWithRemovedParents: new Set(),
@@ -77,17 +91,54 @@ function createAssetGraphRequestRust(rustAtlaspack) {
77
91
  changedAssetsPropagation,
78
92
  previousSymbolPropagationErrors: undefined
79
93
  };
94
+ await input.api.storeResult(result);
95
+ input.api.invalidateOnBuild();
96
+ return result;
80
97
  },
81
98
  input
82
99
  });
83
100
  }
84
- function getAssetGraph(serializedGraph) {
85
- let graph = new _AssetGraph.default({
86
- _contentKeyToNodeId: new Map(),
87
- _nodeIdToContentKey: new Map(),
88
- initialCapacity: serializedGraph.edges.length
89
- });
90
- graph.safeToIncrementallyBundle = false;
101
+ function getAssetGraph(serializedGraph, prevAssetGraph) {
102
+ let graph;
103
+ let reuseEdges = false;
104
+ if (prevAssetGraph && serializedGraph.safeToSkipBundling) {
105
+ graph = new _AssetGraph.default({
106
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
107
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
108
+ nodes: prevAssetGraph.nodes,
109
+ rootNodeId: prevAssetGraph.rootNodeId,
110
+ adjacencyList: prevAssetGraph.adjacencyList
111
+ });
112
+ reuseEdges = true;
113
+ } else if (prevAssetGraph && (serializedGraph.updates.length > 0 || serializedGraph.nodes.length > 0)) {
114
+ graph = new _AssetGraph.default({
115
+ _contentKeyToNodeId: prevAssetGraph._contentKeyToNodeId,
116
+ _nodeIdToContentKey: prevAssetGraph._nodeIdToContentKey,
117
+ nodes: prevAssetGraph.nodes,
118
+ initialCapacity: serializedGraph.edges.length,
119
+ // Accomodate the root node
120
+ initialNodeCapacity: prevAssetGraph.nodes.length + 1,
121
+ rootNodeId: prevAssetGraph.rootNodeId
122
+ });
123
+ graph.safeToIncrementallyBundle = false;
124
+ } else {
125
+ graph = new _AssetGraph.default({
126
+ _contentKeyToNodeId: new Map(),
127
+ _nodeIdToContentKey: new Map(),
128
+ initialCapacity: serializedGraph.edges.length,
129
+ // Accomodate the root node
130
+ initialNodeCapacity: serializedGraph.nodes.length + 1
131
+ });
132
+ let rootNodeId = graph.addNodeByContentKey('@@root', {
133
+ id: '@@root',
134
+ type: 'root',
135
+ value: null
136
+ });
137
+ graph.setRootNodeId(rootNodeId);
138
+ graph.safeToIncrementallyBundle = false;
139
+ }
140
+ (0, _assert().default)(graph, 'Asset graph not initialized');
141
+ (0, _assert().default)(graph.rootNodeId != null, 'Asset graph has no root node');
91
142
 
92
143
  // @ts-expect-error TS7031
93
144
  function mapSymbols({
@@ -118,20 +169,26 @@ function getAssetGraph(serializedGraph) {
118
169
  let envKey = [env.context, env.engines.atlaspack, env.engines.browsers, env.engines.electron, env.engines.node, env.includeNodeModules, env.isLibrary, env.outputFormat, env.shouldScopeHoist, env.shouldOptimize, env.sourceType].join(':');
119
170
  let envId = envs.get(envKey);
120
171
  if (envId == null) {
121
- envId = `${envs.size}`;
172
+ envId = envs.size.toString();
122
173
  envs.set(envKey, envId);
123
174
  }
124
175
  return envId;
125
176
  };
126
- for (let node of serializedGraph.nodes) {
127
- if (node.type === 'root') {
128
- let index = graph.addNodeByContentKey('@@root', {
129
- id: '@@root',
130
- type: 'root',
131
- value: null
132
- });
133
- graph.setRootNodeId(index);
134
- } else if (node.type === 'entry') {
177
+ function updateNode(newNode, isUpdateNode) {
178
+ if (isUpdateNode) {
179
+ let existingNode = graph.getNodeByContentKey(newNode.id);
180
+ (0, _assert().default)(existingNode && existingNode.type === newNode.type);
181
+ Object.assign(existingNode, newNode);
182
+ } else {
183
+ graph.addNodeByContentKey(newNode.id, newNode);
184
+ }
185
+ }
186
+ let nodeTypeSwitchoverIndex = serializedGraph.nodes.length;
187
+ let nodesCount = serializedGraph.nodes.length + serializedGraph.updates.length;
188
+ for (let index = 0; index < nodesCount; index++) {
189
+ let isUpdateNode = index >= nodeTypeSwitchoverIndex;
190
+ let node = isUpdateNode ? serializedGraph.updates[index - nodeTypeSwitchoverIndex] : serializedGraph.nodes[index];
191
+ if (node.type === 'entry') {
135
192
  let id = 'entry:' + ++entry;
136
193
  graph.addNodeByContentKey(id, {
137
194
  id: id,
@@ -159,14 +216,15 @@ function getAssetGraph(serializedGraph) {
159
216
  asset.symbols = new Map(asset.symbols.map(mapSymbols));
160
217
  }
161
218
  changedAssets.set(id, asset);
162
- graph.addNodeByContentKey(id, {
219
+ let assetNode = {
163
220
  id,
164
221
  type: 'asset',
165
222
  usedSymbols: new Set(),
166
223
  usedSymbolsDownDirty: true,
167
224
  usedSymbolsUpDirty: true,
168
225
  value: asset
169
- });
226
+ };
227
+ updateNode(assetNode, isUpdateNode);
170
228
  } else if (node.type === 'dependency') {
171
229
  let {
172
230
  dependency,
@@ -187,7 +245,7 @@ function getAssetGraph(serializedGraph) {
187
245
  usedSymbolsDown.add('*');
188
246
  usedSymbolsUp.set('*', undefined);
189
247
  }
190
- graph.addNodeByContentKey(id, {
248
+ let depNode = {
191
249
  id,
192
250
  type: 'dependency',
193
251
  deferred: false,
@@ -200,21 +258,24 @@ function getAssetGraph(serializedGraph) {
200
258
  usedSymbolsUpDirtyDown: true,
201
259
  usedSymbolsUpDirtyUp: true,
202
260
  value: dependency
203
- });
261
+ };
262
+ updateNode(depNode, isUpdateNode);
204
263
  }
205
264
  }
206
- for (let i = 0; i < serializedGraph.edges.length; i += 2) {
207
- let from = serializedGraph.edges[i];
208
- let to = serializedGraph.edges[i + 1];
209
- let fromNode = graph.getNode(from);
210
- let toNode = graph.getNode(to);
211
- if ((fromNode === null || fromNode === void 0 ? void 0 : fromNode.type) === 'dependency') {
212
- (0, _assert().default)((toNode === null || toNode === void 0 ? void 0 : toNode.type) === 'asset');
213
- }
214
- if ((fromNode === null || fromNode === void 0 ? void 0 : fromNode.type) === 'asset' && (toNode === null || toNode === void 0 ? void 0 : toNode.type) === 'dependency') {
215
- fromNode.value.dependencies.set(toNode.value.id, toNode.value);
265
+ if (!reuseEdges) {
266
+ for (let i = 0; i < serializedGraph.edges.length; i += 2) {
267
+ let from = serializedGraph.edges[i];
268
+ let to = serializedGraph.edges[i + 1];
269
+ let fromNode = graph.getNode(from);
270
+ let toNode = graph.getNode(to);
271
+ if ((fromNode === null || fromNode === void 0 ? void 0 : fromNode.type) === 'dependency') {
272
+ (0, _assert().default)((toNode === null || toNode === void 0 ? void 0 : toNode.type) === 'asset');
273
+ }
274
+ if ((fromNode === null || fromNode === void 0 ? void 0 : fromNode.type) === 'asset' && (toNode === null || toNode === void 0 ? void 0 : toNode.type) === 'dependency') {
275
+ fromNode.value.dependencies.set(toNode.value.id, toNode.value);
276
+ }
277
+ graph.addEdge(from, to);
216
278
  }
217
- graph.addEdge(from, to);
218
279
  }
219
280
  return {
220
281
  assetGraph: graph,
@@ -161,33 +161,23 @@ async function resolveAtlaspackConfig(options) {
161
161
  extendedFiles
162
162
  } = await parseAndProcessConfig(configPath, contents, options);
163
163
  if (options.additionalReporters.length > 0) {
164
- if (options.featureFlags.deduplicateReporters) {
165
- var _config$reporters;
166
- const reporterMap = new Map();
167
- options.additionalReporters.forEach(({
164
+ var _config$reporters;
165
+ const reporterMap = new Map();
166
+ options.additionalReporters.forEach(({
167
+ packageName,
168
+ resolveFrom
169
+ }) => {
170
+ reporterMap.set(packageName, {
168
171
  packageName,
169
172
  resolveFrom
170
- }) => {
171
- reporterMap.set(packageName, {
172
- packageName,
173
- resolveFrom
174
- });
175
- });
176
- (_config$reporters = config.reporters) === null || _config$reporters === void 0 || _config$reporters.forEach(reporter => {
177
- if (!reporterMap.has(reporter.packageName)) {
178
- reporterMap.set(reporter.packageName, reporter);
179
- }
180
173
  });
181
- config.reporters = Array.from(reporterMap.values());
182
- } else {
183
- config.reporters = [...options.additionalReporters.map(({
184
- packageName,
185
- resolveFrom
186
- }) => ({
187
- packageName,
188
- resolveFrom
189
- })), ...(config.reporters ?? [])];
190
- }
174
+ });
175
+ (_config$reporters = config.reporters) === null || _config$reporters === void 0 || _config$reporters.forEach(reporter => {
176
+ if (!reporterMap.has(reporter.packageName)) {
177
+ reporterMap.set(reporter.packageName, reporter);
178
+ }
179
+ });
180
+ config.reporters = Array.from(reporterMap.values());
191
181
  }
192
182
  return {
193
183
  config,
@@ -1,15 +1,14 @@
1
1
  import type { BundleBehavior, DependencyPriority, SpecifierType } from '@atlaspack/types';
2
- export declare class BitFlags<K, V> {
2
+ export declare class BitFlags<K> {
3
3
  #private;
4
- constructor(source: Partial<Record<K, V>>);
5
- into(key: K): V;
6
- intoNullable(key?: K | null): V | null | undefined;
7
- intoArray(keys: K[]): V[];
8
- from(key: V): K;
9
- fromNullable(key?: V | null): K | null | undefined;
10
- fromArray(keys: V[]): K[];
4
+ constructor(source: Partial<Record<K, number>>);
5
+ into(key: K): number;
6
+ intoNullable(key?: K | null): number | null | undefined;
7
+ from(key: number): K;
8
+ fromNullable(key?: number | null): K | null | undefined;
9
+ toArray(keys: number): K[];
11
10
  }
12
- export declare const bundleBehaviorMap: BitFlags<BundleBehavior, number>;
13
- export declare const dependencyPriorityMap: BitFlags<DependencyPriority, number>;
14
- export declare const packageConditionsMap: BitFlags<string, number>;
15
- export declare const specifierTypeMap: BitFlags<SpecifierType, number>;
11
+ export declare const bundleBehaviorMap: BitFlags<BundleBehavior>;
12
+ export declare const dependencyPriorityMap: BitFlags<DependencyPriority>;
13
+ export declare const packageConditionsMap: BitFlags<string>;
14
+ export declare const specifierTypeMap: BitFlags<SpecifierType>;
@@ -14,7 +14,7 @@ type AssetGraphRequest = {
14
14
  input: AssetGraphRequestInput;
15
15
  };
16
16
  export declare function createAssetGraphRequestRust(rustAtlaspack: AtlaspackV3): (input: AssetGraphRequestInput) => AssetGraphRequest;
17
- export declare function getAssetGraph(serializedGraph: any): {
17
+ export declare function getAssetGraph(serializedGraph: any, prevAssetGraph?: AssetGraph): {
18
18
  assetGraph: AssetGraph;
19
19
  changedAssets: Map<string, Asset>;
20
20
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.26.2",
3
+ "version": "2.27.0",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,20 +24,20 @@
24
24
  "dependencies": {
25
25
  "@mischnic/json-sourcemap": "^0.1.0",
26
26
  "@atlaspack/build-cache": "2.13.6",
27
- "@atlaspack/cache": "3.2.32",
27
+ "@atlaspack/cache": "3.2.33",
28
28
  "@atlaspack/diagnostic": "2.14.4",
29
29
  "@atlaspack/events": "2.14.4",
30
- "@atlaspack/feature-flags": "2.26.1",
31
- "@atlaspack/fs": "2.15.32",
32
- "@atlaspack/graph": "3.5.26",
33
- "@atlaspack/logger": "2.14.29",
34
- "@atlaspack/package-manager": "2.14.37",
35
- "@atlaspack/plugin": "2.14.37",
36
- "@atlaspack/profiler": "2.14.34",
37
- "@atlaspack/rust": "3.9.1",
38
- "@atlaspack/types": "2.15.27",
39
- "@atlaspack/utils": "3.1.1",
40
- "@atlaspack/workers": "2.14.37",
30
+ "@atlaspack/feature-flags": "2.26.2",
31
+ "@atlaspack/fs": "2.15.33",
32
+ "@atlaspack/graph": "3.6.0",
33
+ "@atlaspack/logger": "2.14.30",
34
+ "@atlaspack/package-manager": "2.14.38",
35
+ "@atlaspack/plugin": "2.14.38",
36
+ "@atlaspack/profiler": "2.14.35",
37
+ "@atlaspack/rust": "3.10.0",
38
+ "@atlaspack/types": "2.15.28",
39
+ "@atlaspack/utils": "3.1.2",
40
+ "@atlaspack/workers": "2.14.38",
41
41
  "@parcel/source-map": "^2.1.1",
42
42
  "base-x": "^3.0.8",
43
43
  "browserslist": "^4.6.6",
@@ -5,21 +5,20 @@ import type {
5
5
  } from '@atlaspack/types';
6
6
 
7
7
  /// BitFlags is used to map number/string types from napi types
8
- export class BitFlags<K, V> {
8
+ export class BitFlags<K> {
9
9
  // @ts-expect-error TS2344
10
- #kv: Partial<Record<K, V>>;
11
- // @ts-expect-error TS2344
12
- #vk: Partial<Record<V, K>>;
10
+ #kv: Partial<Record<K, number>>;
11
+ #vk: Partial<Record<number, K>>;
13
12
 
14
13
  // @ts-expect-error TS2344
15
- constructor(source: Partial<Record<K, V>>) {
14
+ constructor(source: Partial<Record<K, number>>) {
16
15
  this.#kv = source;
17
16
  this.#vk = Object.fromEntries(
18
17
  Object.entries(source).map((a) => a.reverse()),
19
18
  );
20
19
  }
21
20
 
22
- into(key: K): V {
21
+ into(key: K): number {
23
22
  const found = this.#kv[key];
24
23
  if (found === undefined) {
25
24
  throw new Error(`Invalid BundleBehavior(${key})`);
@@ -27,18 +26,14 @@ export class BitFlags<K, V> {
27
26
  return found;
28
27
  }
29
28
 
30
- intoNullable(key?: K | null): V | null | undefined {
29
+ intoNullable(key?: K | null): number | null | undefined {
31
30
  if (key === undefined || key === null) {
32
31
  return undefined;
33
32
  }
34
33
  return this.into(key);
35
34
  }
36
35
 
37
- intoArray(keys: K[]): V[] {
38
- return keys.map((key) => this.into(key));
39
- }
40
-
41
- from(key: V): K {
36
+ from(key: number): K {
42
37
  const found = this.#vk[key];
43
38
  if (found === undefined) {
44
39
  throw new Error(`Invalid BundleBehavior(${key})`);
@@ -46,52 +41,60 @@ export class BitFlags<K, V> {
46
41
  return found;
47
42
  }
48
43
 
49
- fromNullable(key?: V | null): K | null | undefined {
44
+ fromNullable(key?: number | null): K | null | undefined {
50
45
  if (key === undefined || key === null) {
51
46
  return undefined;
52
47
  }
53
48
  return this.from(key);
54
49
  }
55
50
 
56
- fromArray(keys: V[]): K[] {
57
- return keys.map((key) => this.from(key));
51
+ toArray(keys: number): K[] {
52
+ let values = [];
53
+ for (let [key, value] of Object.entries(this.#kv) as [K, number][]) {
54
+ if ((keys & value) !== 0) {
55
+ values.push(key);
56
+ }
57
+ }
58
+
59
+ return values;
58
60
  }
59
61
  }
60
62
 
61
- export const bundleBehaviorMap: BitFlags<BundleBehavior, number> = new BitFlags(
62
- {
63
- inline: 0,
64
- isolated: 1,
65
- inlineIsolated: 2,
66
- },
67
- );
63
+ export const bundleBehaviorMap: BitFlags<BundleBehavior> = new BitFlags({
64
+ inline: 0,
65
+ isolated: 1,
66
+ inlineIsolated: 2,
67
+ });
68
68
 
69
- export const dependencyPriorityMap: BitFlags<DependencyPriority, number> =
70
- new BitFlags({
69
+ export const dependencyPriorityMap: BitFlags<DependencyPriority> = new BitFlags(
70
+ {
71
71
  sync: 0,
72
72
  parallel: 1,
73
73
  lazy: 2,
74
74
  conditional: 3,
75
- });
75
+ },
76
+ );
76
77
 
77
- export const packageConditionsMap: BitFlags<string, number> = new BitFlags({
78
- import: 0,
79
- require: 1,
80
- module: 2,
81
- node: 3,
82
- browser: 4,
83
- worker: 5,
84
- worklet: 6,
85
- electron: 7,
86
- development: 8,
87
- production: 9,
88
- types: 10,
89
- default: 11,
90
- style: 12,
91
- sass: 13,
78
+ // Note: The bitflags must match the bitflags in the Rust code.
79
+ // crates/atlaspack_core/src/types/package_json.rs
80
+ export const packageConditionsMap: BitFlags<string> = new BitFlags({
81
+ import: 1 << 0,
82
+ require: 1 << 1,
83
+ module: 1 << 2,
84
+ node: 1 << 3,
85
+ browser: 1 << 4,
86
+ worker: 1 << 5,
87
+ worklet: 1 << 6,
88
+ electron: 1 << 7,
89
+ development: 1 << 8,
90
+ production: 1 << 9,
91
+ types: 1 << 10,
92
+ default: 1 << 11,
93
+ style: 1 << 12,
94
+ sass: 1 << 13,
92
95
  });
93
96
 
94
- export const specifierTypeMap: BitFlags<SpecifierType, number> = new BitFlags({
97
+ export const specifierTypeMap: BitFlags<SpecifierType> = new BitFlags({
95
98
  esm: 0,
96
99
  commonjs: 1,
97
100
  url: 2,
@@ -70,7 +70,7 @@ export class Dependency implements IDependency {
70
70
  this.isOptional = inner.isOptional;
71
71
  this.isEntry = inner.isEntry;
72
72
  this.loc = inner.loc;
73
- this.packageConditions = packageConditionsMap.fromArray(
73
+ this.packageConditions = packageConditionsMap.toArray(
74
74
  inner.packageConditions || [],
75
75
  );
76
76
  this.sourceAssetId = inner.sourceAssetId;
@@ -33,27 +33,37 @@ export class AtlaspackWorker {
33
33
  #resolvers: Map<string, ResolverState<any>>;
34
34
  #transformers: Map<string, TransformerState<any>>;
35
35
  #fs: FileSystem;
36
+ #packageManager: NodePackageManager;
36
37
 
37
38
  constructor() {
38
39
  this.#resolvers = new Map();
39
40
  this.#transformers = new Map();
40
41
  this.#fs = new NodeFS();
42
+ this.#packageManager = new NodePackageManager(this.#fs, '/');
41
43
  }
42
44
 
43
45
  loadPlugin: JsCallable<[LoadPluginOptions], Promise<undefined>> = jsCallable(
44
46
  async ({kind, specifier, resolveFrom, featureFlags}) => {
45
- let customRequire = module.createRequire(resolveFrom);
46
- let resolvedPath = customRequire.resolve(specifier);
47
- let resolvedModule = await import(resolvedPath);
47
+ // Use packageManager.require() instead of dynamic import() to support TypeScript plugins
48
+ let resolvedModule = await this.#packageManager.require(
49
+ specifier,
50
+ resolveFrom,
51
+ {shouldAutoInstall: false},
52
+ );
48
53
 
49
54
  let instance = undefined;
50
- if (resolvedModule.default && resolvedModule.default[CONFIG]) {
55
+ // Check for CommonJS export (module.exports = new Plugin(...))
56
+ if (resolvedModule[CONFIG]) {
57
+ instance = resolvedModule[CONFIG];
58
+ } else if (resolvedModule.default && resolvedModule.default[CONFIG]) {
59
+ // ESM default export
51
60
  instance = resolvedModule.default[CONFIG];
52
61
  } else if (
53
62
  resolvedModule.default &&
54
63
  resolvedModule.default.default &&
55
64
  resolvedModule.default.default[CONFIG]
56
65
  ) {
66
+ // Double-wrapped default export
57
67
  instance = resolvedModule.default.default[CONFIG];
58
68
  } else {
59
69
  throw new Error(
@@ -81,7 +81,7 @@ export default function createAssetGraphRequest(
81
81
  await input.api.getPreviousResult<AssetGraphRequestResult>();
82
82
 
83
83
  let builder = new AssetGraphBuilder(input, prevResult);
84
- let assetGraphRequest = await await builder.build();
84
+ let assetGraphRequest = await builder.build();
85
85
 
86
86
  // early break for incremental bundling if production or flag is off;
87
87
  assetGraphRequest.assetGraph.setDisableIncrementalBundling(