@atlaspack/core 2.33.1 → 2.35.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/dist/AssetGraph.js +4 -72
  3. package/dist/BundleGraph.js +34 -0
  4. package/dist/PackagerRunner.js +13 -88
  5. package/dist/RequestTracker.js +17 -80
  6. package/dist/TargetDescriptor.schema.js +3 -0
  7. package/dist/UncommittedAsset.js +0 -5
  8. package/dist/applyRuntimes.js +2 -1
  9. package/dist/atlaspack-v3/AtlaspackV3.js +6 -2
  10. package/dist/requests/AssetGraphRequest.js +6 -15
  11. package/dist/requests/AssetGraphRequestRust.js +119 -22
  12. package/dist/requests/AtlaspackBuildRequest.js +8 -2
  13. package/dist/requests/BundleGraphRequest.js +9 -15
  14. package/dist/requests/BundleGraphRequestRust.js +1 -2
  15. package/dist/requests/PackageRequest.js +1 -1
  16. package/dist/requests/TargetRequest.js +5 -0
  17. package/dist/requests/WriteBundleRequest.js +129 -12
  18. package/dist/requests/WriteBundlesRequest.js +15 -9
  19. package/dist/resolveOptions.js +2 -4
  20. package/lib/AssetGraph.js +3 -62
  21. package/lib/BundleGraph.js +38 -0
  22. package/lib/PackagerRunner.js +13 -77
  23. package/lib/RequestTracker.js +15 -69
  24. package/lib/TargetDescriptor.schema.js +3 -0
  25. package/lib/UncommittedAsset.js +0 -11
  26. package/lib/applyRuntimes.js +1 -1
  27. package/lib/atlaspack-v3/AtlaspackV3.js +6 -2
  28. package/lib/requests/AssetGraphRequest.js +4 -18
  29. package/lib/requests/AssetGraphRequestRust.js +88 -23
  30. package/lib/requests/AtlaspackBuildRequest.js +8 -2
  31. package/lib/requests/BundleGraphRequest.js +12 -16
  32. package/lib/requests/BundleGraphRequestRust.js +2 -3
  33. package/lib/requests/PackageRequest.js +3 -1
  34. package/lib/requests/TargetRequest.js +5 -0
  35. package/lib/requests/WriteBundleRequest.js +131 -8
  36. package/lib/requests/WriteBundlesRequest.js +12 -5
  37. package/lib/resolveOptions.js +2 -4
  38. package/lib/types/AssetGraph.d.ts +2 -27
  39. package/lib/types/BundleGraph.d.ts +5 -0
  40. package/lib/types/atlaspack-v3/AtlaspackV3.d.ts +3 -2
  41. package/lib/types/requests/BundleGraphRequest.d.ts +1 -1
  42. package/lib/types/requests/WriteBundleRequest.d.ts +20 -1
  43. package/lib/types/types.d.ts +1 -0
  44. package/package.json +15 -15
  45. package/src/AssetGraph.ts +4 -72
  46. package/src/BundleGraph.ts +39 -0
  47. package/src/PackagerRunner.ts +15 -101
  48. package/src/RequestTracker.ts +24 -110
  49. package/src/TargetDescriptor.schema.ts +3 -0
  50. package/src/UncommittedAsset.ts +1 -11
  51. package/src/applyRuntimes.ts +3 -1
  52. package/src/atlaspack-v3/AtlaspackV3.ts +19 -3
  53. package/src/requests/AssetGraphRequest.ts +8 -20
  54. package/src/requests/AssetGraphRequestRust.ts +96 -23
  55. package/src/requests/AtlaspackBuildRequest.ts +16 -8
  56. package/src/requests/BundleGraphRequest.ts +12 -30
  57. package/src/requests/BundleGraphRequestRust.ts +1 -2
  58. package/src/requests/PackageRequest.ts +1 -1
  59. package/src/requests/TargetRequest.ts +5 -0
  60. package/src/requests/WriteBundleRequest.ts +177 -13
  61. package/src/requests/WriteBundlesRequest.ts +25 -13
  62. package/src/resolveOptions.ts +2 -4
  63. package/src/types.ts +1 -0
  64. package/test/AssetGraph.test.ts +0 -32
  65. package/test/RequestTracker.test.ts +0 -165
  66. package/test/TargetRequest.test.ts +25 -0
  67. package/test/requests/WriteBundleRequest.test.ts +239 -0
  68. package/tsconfig.tsbuildinfo +1 -1
@@ -3,6 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.applyReplacementsToSourceMap = applyReplacementsToSourceMap;
7
+ exports.computeSourceMapRoot = computeSourceMapRoot;
6
8
  exports.default = createWriteBundleRequest;
7
9
  var _constants = require("../constants");
8
10
  function _nullthrows() {
@@ -19,6 +21,13 @@ function _path() {
19
21
  };
20
22
  return data;
21
23
  }
24
+ function _url() {
25
+ const data = _interopRequireDefault(require("url"));
26
+ _url = function () {
27
+ return data;
28
+ };
29
+ return data;
30
+ }
22
31
  var _Bundle = require("../public/Bundle");
23
32
  function _utils() {
24
33
  const data = require("@atlaspack/utils");
@@ -68,11 +77,19 @@ function _featureFlags() {
68
77
  return data;
69
78
  }
70
79
  var _EnvironmentManager = require("../EnvironmentManager");
80
+ function _sourceMap() {
81
+ const data = _interopRequireDefault(require("@atlaspack/source-map"));
82
+ _sourceMap = function () {
83
+ return data;
84
+ };
85
+ return data;
86
+ }
71
87
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
72
88
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
73
89
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
74
90
  const HASH_REF_PREFIX_LEN = _constants.HASH_REF_PREFIX.length;
75
91
  const BOUNDARY_LENGTH = _constants.HASH_REF_PREFIX.length + 32 - 1;
92
+ const HASH_REF_PLACEHOLDER_LEN = HASH_REF_PREFIX_LEN + _constants.HASH_REF_HASH_LEN;
76
93
  /**
77
94
  * Writes a bundle to the dist directory, replacing hash references with the final content hashes.
78
95
  */
@@ -158,11 +175,28 @@ async function run({
158
175
  invalidDevDeps
159
176
  } = await (0, _DevDepRequest.getDevDepRequests)(api);
160
177
  (0, _DevDepRequest.invalidateDevDeps)(invalidDevDeps, options, config);
161
- await writeFiles(contentStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api);
162
- const hasSourceMap = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await options.cache.hasLargeBlob(mapKey) : await options.cache.has(mapKey);
178
+ const bundleReplacements = (0, _featureFlags().getFeatureFlag)('fixSourceMapHashRefs') ? [] : undefined;
179
+ await writeFiles(contentStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api, bundleReplacements);
180
+ const hasSourceMap = await options.cache.has(mapKey);
163
181
  if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
164
- const mapEntry = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await options.cache.getLargeBlob(mapKey) : await options.cache.getBlob(mapKey);
165
- await writeFiles((0, _utils().blobToStream)(mapEntry), info, hashRefToNameHash, options, config, outputFS, (0, _projectPath.toProjectPathUnsafe)((0, _projectPath.fromProjectPathRelative)(filePath) + '.map'), writeOptions, devDeps, api);
182
+ let mapStream;
183
+ if ((0, _featureFlags().getFeatureFlag)('fixSourceMapHashRefs') && bundleReplacements && bundleReplacements.length > 0) {
184
+ const mapEntry = await options.cache.getBlob(mapKey);
185
+ const mapBuffer = Buffer.isBuffer(mapEntry) ? mapEntry : Buffer.from(mapEntry);
186
+ const projectRoot = typeof options.projectRoot === 'string' ? options.projectRoot : String(options.projectRoot);
187
+ const sourceMap = new (_sourceMap().default)(projectRoot, mapBuffer);
188
+ applyReplacementsToSourceMap(sourceMap, bundleReplacements);
189
+ const mapJson = await sourceMap.stringify({
190
+ format: 'string',
191
+ file: name,
192
+ sourceRoot: computeSourceMapRoot(bundle, options)
193
+ });
194
+ mapStream = (0, _utils().blobToStream)(Buffer.from(typeof mapJson === 'string' ? mapJson : JSON.stringify(mapJson), 'utf8'));
195
+ } else {
196
+ const mapEntry = await options.cache.getBlob(mapKey);
197
+ mapStream = (0, _utils().blobToStream)(mapEntry);
198
+ }
199
+ await writeFiles(mapStream, info, hashRefToNameHash, options, config, outputFS, (0, _projectPath.toProjectPathUnsafe)((0, _projectPath.fromProjectPathRelative)(filePath) + '.map'), writeOptions, devDeps, api);
166
200
  }
167
201
  let res = {
168
202
  filePath,
@@ -176,12 +210,71 @@ async function run({
176
210
  api.storeResult(res);
177
211
  return res;
178
212
  }
213
+ function applyReplacementsToSourceMap(sourceMap, replacements) {
214
+ if (replacements.length === 0) return;
215
+ const sorted = [...replacements].sort((a, b) => a.line - b.line || a.column - b.column);
216
+ for (const r of sorted) {
217
+ const delta = r.newLength - r.originalLength;
218
+ if (delta !== 0) {
219
+ // r.column is in post-replacement coordinates (matching the already-shifted
220
+ // source map state after previous offsetColumns calls). The end of the
221
+ // placeholder in these coordinates is simply r.column + r.originalLength.
222
+ const offsetStartColumn = r.column + r.originalLength;
223
+ const line1Based = r.line + 1;
224
+ if (line1Based >= 1 && offsetStartColumn + delta >= 0) {
225
+ sourceMap.offsetColumns(line1Based, offsetStartColumn, delta);
226
+ }
227
+ }
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Computes the sourceRoot for a source map file. This is the relative path from
233
+ * the output directory back to the project root, so that source paths (stored
234
+ * relative to projectRoot) resolve correctly from the .map file location.
235
+ *
236
+ * Returns undefined when sources are inlined (inlineSources), since the browser
237
+ * doesn't need to fetch them and sourceRoot would be unnecessary.
238
+ *
239
+ * This logic must stay in sync with PackagerRunner.generateSourceMap.
240
+ */
241
+ function computeSourceMapRoot(bundle, options) {
242
+ let name = (0, _nullthrows().default)(bundle.name);
243
+ let filePath = (0, _projectPath.joinProjectPath)(bundle.target.distDir, name);
244
+ let fullPath = (0, _projectPath.fromProjectPath)(options.projectRoot, filePath);
245
+ let sourceRoot = _path().default.relative(_path().default.dirname(fullPath), options.projectRoot);
246
+ let inlineSources = false;
247
+ const bundleEnv = (0, _EnvironmentManager.fromEnvironmentId)(bundle.env);
248
+ if (bundle.target) {
249
+ const bundleTargetEnv = (0, _EnvironmentManager.fromEnvironmentId)(bundle.target.env);
250
+ if (bundleEnv.sourceMap && bundleEnv.sourceMap.sourceRoot !== undefined) {
251
+ sourceRoot = bundleEnv.sourceMap.sourceRoot;
252
+ } else if (options.serveOptions && bundleTargetEnv.context === 'browser') {
253
+ sourceRoot = '/__parcel_source_root';
254
+ }
255
+ if (bundleEnv.sourceMap && bundleEnv.sourceMap.inlineSources !== undefined) {
256
+ inlineSources = bundleEnv.sourceMap.inlineSources;
257
+ } else if (bundleTargetEnv.context !== 'node') {
258
+ inlineSources = options.mode === 'production';
259
+ }
260
+ }
261
+ let isInlineMap = bundleEnv.sourceMap && bundleEnv.sourceMap.inline;
262
+ if ((0, _featureFlags().getFeatureFlag)('omitSourcesContentInMemory') && !isInlineMap) {
263
+ if (!(bundleEnv.sourceMap && bundleEnv.sourceMap.inlineSources === false)) {
264
+ inlineSources = true;
265
+ }
266
+ }
267
+ if (inlineSources) {
268
+ return undefined;
269
+ }
270
+ return _url().default.format(_url().default.parse(sourceRoot + '/'));
271
+ }
179
272
  async function writeFiles(
180
273
  // @ts-expect-error TS2503
181
- inputStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api) {
274
+ inputStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api, bundleReplacements) {
182
275
  let compressors = await config.getCompressors((0, _projectPath.fromProjectPathRelative)(filePath));
183
276
  let fullPath = (0, _projectPath.fromProjectPath)(options.projectRoot, filePath);
184
- let stream = info.hashReferences.length ? inputStream.pipe(replaceStream(hashRefToNameHash)) : inputStream;
277
+ let stream = info.hashReferences.length ? inputStream.pipe(replaceStream(hashRefToNameHash, bundleReplacements)) : inputStream;
185
278
  let promises = [];
186
279
  for (let compressor of compressors) {
187
280
  promises.push(
@@ -230,9 +323,25 @@ stream, options, outputFS, filePath, writeOptions, devDeps, api) {
230
323
  await (0, _DevDepRequest.runDevDepRequest)(api, devDepRequest);
231
324
  }
232
325
  }
233
- function replaceStream(hashRefToNameHash) {
326
+ function advanceLineColumn(line, column, buf) {
327
+ for (let i = 0; i < buf.length; i++) {
328
+ if (buf[i] === 0x0a) {
329
+ line++;
330
+ column = 0;
331
+ } else {
332
+ column++;
333
+ }
334
+ }
335
+ return {
336
+ line,
337
+ column
338
+ };
339
+ }
340
+ function replaceStream(hashRefToNameHash, replacements) {
234
341
  let boundaryStr = Buffer.alloc(0);
235
342
  let replaced = Buffer.alloc(0);
343
+ let outputLine = 0;
344
+ let outputColumn = 0;
236
345
  return new (_stream().Transform)({
237
346
  transform(chunk, encoding, cb) {
238
347
  let str = Buffer.concat([boundaryStr, Buffer.from(chunk)]);
@@ -250,15 +359,29 @@ function replaceStream(hashRefToNameHash) {
250
359
  } else {
251
360
  let match = str.subarray(matchI, matchI + HASH_REF_PREFIX_LEN + _constants.HASH_REF_HASH_LEN).toString();
252
361
  let replacement = Buffer.from(hashRefToNameHash.get(match) ?? match);
362
+ // Copy pre-match content FIRST so position calculation includes it
253
363
  replaced.set(str.subarray(lastMatchI, matchI), replacedLength);
254
364
  replacedLength += matchI - lastMatchI;
365
+ if (replacements) {
366
+ const pos = advanceLineColumn(outputLine, outputColumn, replaced.subarray(0, replacedLength));
367
+ replacements.push({
368
+ line: pos.line,
369
+ column: pos.column,
370
+ originalLength: HASH_REF_PLACEHOLDER_LEN,
371
+ newLength: replacement.byteLength
372
+ });
373
+ }
255
374
  replaced.set(replacement, replacedLength);
256
375
  replacedLength += replacement.byteLength;
257
376
  lastMatchI = matchI + HASH_REF_PREFIX_LEN + _constants.HASH_REF_HASH_LEN;
258
377
  }
259
378
  }
379
+ const pushLen = replacedLength - BOUNDARY_LENGTH;
380
+ const pushed = advanceLineColumn(outputLine, outputColumn, replaced.subarray(0, pushLen));
381
+ outputLine = pushed.line;
382
+ outputColumn = pushed.column;
260
383
  boundaryStr = replaced.subarray(replacedLength - BOUNDARY_LENGTH, replacedLength);
261
- let strUpToBoundary = replaced.subarray(0, replacedLength - BOUNDARY_LENGTH);
384
+ let strUpToBoundary = replaced.subarray(0, pushLen);
262
385
  cb(null, strUpToBoundary);
263
386
  },
264
387
  flush(cb) {
@@ -40,6 +40,13 @@ function _utils() {
40
40
  return data;
41
41
  }
42
42
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
43
+ /** Length of the hash suffix in output filenames (e.g. .runtime.13dc01ac.js). */
44
+ const NAME_HASH_DISPLAY_LEN = 8;
45
+
46
+ /** Use at most NAME_HASH_DISPLAY_LEN chars for the name hash so filenames stay short. */
47
+ function nameHashForFilename(hash) {
48
+ return hash.length <= NAME_HASH_DISPLAY_LEN ? hash : hash.slice(-NAME_HASH_DISPLAY_LEN);
49
+ }
43
50
  function reportPackagingProgress(completeBundles, totalBundles) {
44
51
  if (!(0, _featureFlags().getFeatureFlag)('cliProgressReportingImprovements')) {
45
52
  return;
@@ -92,9 +99,9 @@ async function run({
92
99
  // Do not package and write placeholder bundles to disk. We just
93
100
  // need to update the name so other bundles can reference it.
94
101
  if (bundle.isPlaceholder) {
95
- let hash = bundle.id.slice(-8);
96
- hashRefToNameHash.set(bundle.hashReference, hash);
97
- let name = (0, _nullthrows().default)(bundle.name, `Expected ${bundle.type} bundle to have a name`).replace(bundle.hashReference, hash);
102
+ const nameHash = nameHashForFilename(bundle.id);
103
+ hashRefToNameHash.set(bundle.hashReference, nameHash);
104
+ let name = (0, _nullthrows().default)(bundle.name, `Expected ${bundle.type} bundle to have a name`).replace(bundle.hashReference, nameHash);
98
105
  res.set(bundle.id, {
99
106
  filePath: (0, _projectPath.joinProjectPath)(bundle.target.distDir, name),
100
107
  bundleId: bundle.id,
@@ -143,7 +150,7 @@ async function run({
143
150
  }
144
151
  bundleInfoMap[bundle.id] = info;
145
152
  if (!info.hashReferences.length) {
146
- hashRefToNameHash.set(bundle.hashReference, options.shouldContentHash ? info.hash.slice(-8) : bundle.id.slice(-8));
153
+ hashRefToNameHash.set(bundle.hashReference, nameHashForFilename(options.shouldContentHash ? info.hash : bundle.id));
147
154
  let writeBundleRequest = (0, _WriteBundleRequest.default)({
148
155
  bundle,
149
156
  info,
@@ -195,7 +202,7 @@ function assignComplexNameHashes(hashRefToNameHash, bundles, bundleInfoMap, opti
195
202
  if (hashRefToNameHash.get(bundle.hashReference) != null) {
196
203
  continue;
197
204
  }
198
- hashRefToNameHash.set(bundle.hashReference, options.shouldContentHash ? (0, _rust().hashString)([...getBundlesIncludedInHash(bundle.id, bundleInfoMap)].map(bundleId => bundleInfoMap[bundleId].hash).join(':')).slice(-8) : bundle.id.slice(-8));
205
+ hashRefToNameHash.set(bundle.hashReference, nameHashForFilename(options.shouldContentHash ? (0, _rust().hashString)([...getBundlesIncludedInHash(bundle.id, bundleInfoMap)].map(bundleId => bundleInfoMap[bundleId].hash).join(':')) : bundle.id));
199
206
  }
200
207
  }
201
208
  function getBundlesIncludedInHash(bundleId, bundleInfoMap, included = new Set()) {
@@ -167,10 +167,8 @@ async function resolveOptions(initialOptions) {
167
167
  return initialOptions.cache;
168
168
  }
169
169
  const needsRustLmdbCache = (0, _featureFlags().getFeatureFlag)('atlaspackV3') || (0, _featureFlags().getFeatureFlag)('nativePackager');
170
- if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
171
- if (!needsRustLmdbCache && !(outputFS instanceof _fs().NodeFS)) {
172
- return new (_cache().FSCache)(outputFS, cacheDir);
173
- }
170
+ if (!needsRustLmdbCache && !(outputFS instanceof _fs().NodeFS)) {
171
+ return new (_cache().FSCache)(outputFS, cacheDir);
174
172
  }
175
173
  return new (_cache().LMDBLiteCache)(cacheDir);
176
174
  }
@@ -9,13 +9,9 @@ type InitOpts = {
9
9
  assetGroups?: Array<AssetGroup>;
10
10
  };
11
11
  type AssetGraphOpts = ContentGraphOpts<AssetGraphNode> & {
12
- bundlingVersion?: number;
13
- disableIncrementalBundling?: boolean;
14
12
  hash?: string | null | undefined;
15
13
  };
16
14
  type SerializedAssetGraph = SerializedContentGraph<AssetGraphNode> & {
17
- bundlingVersion: number;
18
- disableIncrementalBundling: boolean;
19
15
  hash?: string | null | undefined;
20
16
  };
21
17
  export declare function nodeFromDep(dep: Dependency): DependencyNode;
@@ -24,40 +20,19 @@ export declare function nodeFromAsset(asset: Asset): AssetNode;
24
20
  export declare function nodeFromEntrySpecifier(entry: ProjectPath): EntrySpecifierNode;
25
21
  export declare function nodeFromEntryFile(entry: Entry): EntryFileNode;
26
22
  export default class AssetGraph extends ContentGraph<AssetGraphNode> {
27
- #private;
28
23
  onNodeRemoved: ((nodeId: NodeId) => unknown) | null | undefined;
29
24
  hash: string | null | undefined;
30
25
  envCache: Map<string, Environment>;
31
- /**
32
- * @deprecated
33
- */
34
26
  safeToIncrementallyBundle: boolean;
35
27
  undeferredDependencies: Set<Dependency>;
36
28
  constructor(opts?: AssetGraphOpts | null);
37
29
  static deserialize(opts: AssetGraphOpts): AssetGraph;
38
30
  serialize(): SerializedAssetGraph;
39
31
  /**
40
- * Force incremental bundling to be disabled.
41
- */
42
- setDisableIncrementalBundling(disable: boolean): void;
43
- testing_getDisableIncrementalBundling(): boolean;
44
- /**
45
- * Make sure this asset graph is marked as needing a full bundling pass.
46
- */
47
- setNeedsBundling(): void;
48
- /**
49
- * Get the current bundling version.
50
- *
51
- * Each bundle pass should keep this version around. Whenever an asset graph has a new version,
52
- * bundling should be re-run.
53
- */
54
- getBundlingVersion(): number;
55
- /**
56
- * If the `bundlingVersion` has not changed since the last bundling pass,
57
- * we can incrementally bundle, which will not require a full bundling pass
32
+ * Determine if we can incrementally bundle, which will not require a full bundling pass
58
33
  * but just update assets into the bundle graph output.
59
34
  */
60
- canIncrementallyBundle(lastVersion: number): boolean;
35
+ canIncrementallyBundle(): boolean;
61
36
  normalizeEnvironment(input: Asset | Dependency | AssetGroup): void;
62
37
  setRootConnections({ entries, assetGroups }: InitOpts): void;
63
38
  addNode(node: AssetGraphNode): NodeId;
@@ -87,6 +87,11 @@ export default class BundleGraph {
87
87
  publicIdByAssetId: Record<string, string>;
88
88
  environmentsJson: string;
89
89
  };
90
+ /**
91
+ * Serialize only the given asset nodes for native incremental update.
92
+ * Same node shape and env/omit logic as serializeForNative.
93
+ */
94
+ serializeAssetNodesForNative(assetIds: Array<string>): string;
90
95
  /**
91
96
  * Remove null and undefined values from an object to reduce JSON size.
92
97
  * Preserves false, 0, empty strings, and arrays.
@@ -1,4 +1,4 @@
1
- import { AtlaspackNapi, Lmdb, AtlaspackNapiOptions, CacheStats } from '@atlaspack/rust';
1
+ import { AtlaspackNapi, Lmdb, AtlaspackNapiOptions, CacheStats, PackageOptions } from '@atlaspack/rust';
2
2
  import { Diagnostic } from '@atlaspack/diagnostic';
3
3
  import type { Event } from '@parcel/watcher';
4
4
  import type { NapiWorkerPool as INapiWorkerPool } from '@atlaspack/types';
@@ -27,7 +27,8 @@ export declare class AtlaspackV3 {
27
27
  buildAssetGraph(): Promise<any>;
28
28
  buildBundleGraph(): Promise<any>;
29
29
  loadBundleGraph(bundleGraph: BundleGraph): Promise<void>;
30
- package(bundleId: string): Promise<[RunPackagerRunnerResult, Diagnostic | null]>;
30
+ updateBundleGraph(bundleGraph: BundleGraph, changedAssetIds: string[]): Promise<void>;
31
+ package(bundleId: string, options?: PackageOptions): Promise<[RunPackagerRunnerResult, Diagnostic | null]>;
31
32
  respondToFsEvents(events: Array<Event>): Promise<boolean>;
32
33
  completeCacheSession(): Promise<CacheStats>;
33
34
  }
@@ -14,9 +14,9 @@ type RunInput = {
14
14
  } & StaticRunOpts<BundleGraphResult>;
15
15
  export type BundleGraphResult = {
16
16
  bundleGraph: InternalBundleGraph;
17
- assetGraphBundlingVersion: number;
18
17
  changedAssets: Map<string, Asset>;
19
18
  assetRequests: Array<AssetGroup>;
19
+ didIncrementallyBundle: boolean;
20
20
  };
21
21
  type BundleGraphRequest = {
22
22
  id: string;
@@ -1,10 +1,17 @@
1
1
  import type { ContentKey } from '@atlaspack/graph';
2
2
  import type { Async } from '@atlaspack/types';
3
3
  import type { StaticRunOpts } from '../RequestTracker';
4
- import type { Bundle, PackagedBundleInfo } from '../types';
4
+ import type { Bundle, PackagedBundleInfo, AtlaspackOptions } from '../types';
5
5
  import type BundleGraph from '../BundleGraph';
6
6
  import type { BundleInfo } from '../PackagerRunner';
7
7
  import { requestTypes } from '../RequestTracker';
8
+ import SourceMap from '@atlaspack/source-map';
9
+ export type HashRefReplacement = {
10
+ line: number;
11
+ column: number;
12
+ originalLength: number;
13
+ newLength: number;
14
+ };
8
15
  type WriteBundleRequestInput = {
9
16
  bundleGraph: BundleGraph;
10
17
  bundle: Bundle;
@@ -25,4 +32,16 @@ export type WriteBundleRequest = {
25
32
  * Writes a bundle to the dist directory, replacing hash references with the final content hashes.
26
33
  */
27
34
  export default function createWriteBundleRequest(input: WriteBundleRequestInput): WriteBundleRequest;
35
+ export declare function applyReplacementsToSourceMap(sourceMap: SourceMap, replacements: HashRefReplacement[]): void;
36
+ /**
37
+ * Computes the sourceRoot for a source map file. This is the relative path from
38
+ * the output directory back to the project root, so that source paths (stored
39
+ * relative to projectRoot) resolve correctly from the .map file location.
40
+ *
41
+ * Returns undefined when sources are inlined (inlineSources), since the browser
42
+ * doesn't need to fetch them and sourceRoot would be unnecessary.
43
+ *
44
+ * This logic must stay in sync with PackagerRunner.generateSourceMap.
45
+ */
46
+ export declare function computeSourceMapRoot(bundle: Bundle, options: AtlaspackOptions): string | undefined;
28
47
  export {};
@@ -70,6 +70,7 @@ export type Target = {
70
70
  loc?: InternalSourceLocation | null | undefined;
71
71
  pipeline?: string;
72
72
  source?: FilePath | Array<FilePath>;
73
+ inlineRequires?: boolean;
73
74
  };
74
75
  export declare const SpecifierType: {
75
76
  readonly esm: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.33.1",
3
+ "version": "2.35.0",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -23,22 +23,22 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@mischnic/json-sourcemap": "^0.1.0",
26
- "@atlaspack/build-cache": "2.13.11",
27
- "@atlaspack/cache": "3.2.48",
26
+ "@atlaspack/build-cache": "2.13.13",
27
+ "@atlaspack/cache": "3.2.50",
28
28
  "@atlaspack/diagnostic": "2.14.4",
29
29
  "@atlaspack/events": "2.14.4",
30
- "@atlaspack/feature-flags": "2.29.1",
31
- "@atlaspack/fs": "2.15.48",
32
- "@atlaspack/graph": "3.6.15",
33
- "@atlaspack/logger": "2.14.45",
34
- "@atlaspack/package-manager": "2.14.53",
35
- "@atlaspack/plugin": "2.14.53",
36
- "@atlaspack/profiler": "2.15.14",
37
- "@atlaspack/rust": "3.22.1",
38
- "@atlaspack/types": "2.15.43",
39
- "@atlaspack/utils": "3.3.5",
40
- "@atlaspack/workers": "2.14.53",
41
- "@atlaspack/source-map": "3.2.8",
30
+ "@atlaspack/feature-flags": "2.30.1",
31
+ "@atlaspack/fs": "2.15.50",
32
+ "@atlaspack/graph": "3.6.17",
33
+ "@atlaspack/logger": "2.14.47",
34
+ "@atlaspack/package-manager": "2.14.55",
35
+ "@atlaspack/plugin": "2.14.55",
36
+ "@atlaspack/profiler": "2.15.16",
37
+ "@atlaspack/rust": "3.24.0",
38
+ "@atlaspack/types": "2.15.45",
39
+ "@atlaspack/utils": "3.3.7",
40
+ "@atlaspack/workers": "2.14.55",
41
+ "@atlaspack/source-map": "3.2.10",
42
42
  "base-x": "^3.0.8",
43
43
  "browserslist": "^4.6.6",
44
44
  "clone": "^2.1.1",
package/src/AssetGraph.ts CHANGED
@@ -41,14 +41,10 @@ type InitOpts = {
41
41
  };
42
42
 
43
43
  type AssetGraphOpts = ContentGraphOpts<AssetGraphNode> & {
44
- bundlingVersion?: number;
45
- disableIncrementalBundling?: boolean;
46
44
  hash?: string | null | undefined;
47
45
  };
48
46
 
49
47
  type SerializedAssetGraph = SerializedContentGraph<AssetGraphNode> & {
50
- bundlingVersion: number;
51
- disableIncrementalBundling: boolean;
52
48
  hash?: string | null | undefined;
53
49
  };
54
50
 
@@ -121,30 +117,16 @@ export default class AssetGraph extends ContentGraph<AssetGraphNode> {
121
117
  hash: string | null | undefined;
122
118
  envCache: Map<string, Environment>;
123
119
 
124
- /**
125
- * Incremented when the asset graph is modified such that it requires a bundling pass.
126
- */
127
- #bundlingVersion: number = 0;
128
- /**
129
- * Force incremental bundling to be disabled.
130
- */
131
- #disableIncrementalBundling: boolean = false;
132
-
133
- /**
134
- * @deprecated
135
- */
136
120
  safeToIncrementallyBundle: boolean = true;
137
121
 
138
122
  undeferredDependencies: Set<Dependency>;
139
123
 
140
124
  constructor(opts?: AssetGraphOpts | null) {
141
125
  if (opts) {
142
- let {hash, bundlingVersion, disableIncrementalBundling, ...rest} = opts;
126
+ let {hash, ...rest} = opts;
143
127
  // @ts-expect-error TS2345
144
128
  super(rest);
145
129
  this.hash = hash;
146
- this.#bundlingVersion = bundlingVersion ?? 0;
147
- this.#disableIncrementalBundling = disableIncrementalBundling ?? false;
148
130
  } else {
149
131
  super();
150
132
  this.setRootNodeId(
@@ -167,64 +149,16 @@ export default class AssetGraph extends ContentGraph<AssetGraphNode> {
167
149
  serialize(): SerializedAssetGraph {
168
150
  return {
169
151
  ...super.serialize(),
170
- bundlingVersion: this.#bundlingVersion,
171
- disableIncrementalBundling: this.#disableIncrementalBundling,
172
152
  hash: this.hash,
173
153
  };
174
154
  }
175
155
 
176
156
  /**
177
- * Force incremental bundling to be disabled.
178
- */
179
- setDisableIncrementalBundling(disable: boolean) {
180
- this.#disableIncrementalBundling = disable;
181
- }
182
-
183
- testing_getDisableIncrementalBundling(): boolean {
184
- return this.#disableIncrementalBundling;
185
- }
186
-
187
- /**
188
- * Make sure this asset graph is marked as needing a full bundling pass.
189
- */
190
- setNeedsBundling() {
191
- if (!getFeatureFlag('incrementalBundlingVersioning')) {
192
- // In legacy mode, we rely solely on safeToIncrementallyBundle to
193
- // invalidate incremental bundling, so we skip bumping the version.
194
- return;
195
- }
196
- this.#bundlingVersion += 1;
197
- }
198
-
199
- /**
200
- * Get the current bundling version.
201
- *
202
- * Each bundle pass should keep this version around. Whenever an asset graph has a new version,
203
- * bundling should be re-run.
204
- */
205
- getBundlingVersion(): number {
206
- if (!getFeatureFlag('incrementalBundlingVersioning')) {
207
- return 0;
208
- }
209
- return this.#bundlingVersion;
210
- }
211
-
212
- /**
213
- * If the `bundlingVersion` has not changed since the last bundling pass,
214
- * we can incrementally bundle, which will not require a full bundling pass
157
+ * Determine if we can incrementally bundle, which will not require a full bundling pass
215
158
  * but just update assets into the bundle graph output.
216
159
  */
217
- canIncrementallyBundle(lastVersion: number): boolean {
218
- if (!getFeatureFlag('incrementalBundlingVersioning')) {
219
- return (
220
- this.safeToIncrementallyBundle && !this.#disableIncrementalBundling
221
- );
222
- }
223
- return (
224
- this.safeToIncrementallyBundle &&
225
- this.#bundlingVersion === lastVersion &&
226
- !this.#disableIncrementalBundling
227
- );
160
+ canIncrementallyBundle(): boolean {
161
+ return this.safeToIncrementallyBundle;
228
162
  }
229
163
 
230
164
  // Deduplicates Environments by making them referentially equal
@@ -447,13 +381,11 @@ export default class AssetGraph extends ContentGraph<AssetGraphNode> {
447
381
  // @ts-expect-error TS2339
448
382
  if (!ctx?.hasDeferred) {
449
383
  this.safeToIncrementallyBundle = false;
450
- this.setNeedsBundling();
451
384
  delete traversedNode.hasDeferred;
452
385
  }
453
386
  actions.skipChildren();
454
387
  } else if (traversedNode.type === 'dependency') {
455
388
  this.safeToIncrementallyBundle = false;
456
- this.setNeedsBundling();
457
389
  traversedNode.hasDeferred = false;
458
390
  } else if (nodeId !== traversedNodeId) {
459
391
  actions.skipChildren();
@@ -654,6 +654,45 @@ export default class BundleGraph {
654
654
  return {nodesJson, edges, publicIdByAssetId, environmentsJson};
655
655
  }
656
656
 
657
+ /**
658
+ * Serialize only the given asset nodes for native incremental update.
659
+ * Same node shape and env/omit logic as serializeForNative.
660
+ */
661
+ serializeAssetNodesForNative(assetIds: Array<string>): string {
662
+ const start = performance.now();
663
+
664
+ if (assetIds.length === 0) {
665
+ return '[]';
666
+ }
667
+
668
+ const nodes: Array<BundleGraphNode> = [];
669
+ for (const assetId of assetIds) {
670
+ const node = this._graph.getNodeByContentKey(assetId);
671
+ if (node?.type !== 'asset') {
672
+ continue;
673
+ }
674
+ const processedNode = {...node};
675
+ if (node.value?.env) {
676
+ processedNode.value = {
677
+ ...node.value,
678
+ env: fromEnvironmentId(node.value.env).id,
679
+ };
680
+ }
681
+ nodes.push(processedNode);
682
+ }
683
+ const optimizedNodes = nodes.map((node) => this._omitNulls(node));
684
+ const nodesJson = JSON.stringify(optimizedNodes);
685
+
686
+ const duration = performance.now() - start;
687
+ const nodesSizeMB = (nodesJson.length / (1024 * 1024)).toFixed(2);
688
+
689
+ logger.verbose({
690
+ origin: '@atlaspack/core',
691
+ message: `serializeAssetNodesForNative: ${duration.toFixed(1)}ms, ${nodesSizeMB}MB nodes, ${nodes.length} nodes`,
692
+ });
693
+ return nodesJson;
694
+ }
695
+
657
696
  /**
658
697
  * Remove null and undefined values from an object to reduce JSON size.
659
698
  * Preserves false, 0, empty strings, and arrays.