@atlaspack/core 2.24.1 → 2.24.2-dev-ts-project-refs-d30e9754f.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 (86) hide show
  1. package/LICENSE +201 -0
  2. package/dist/AssetGraph.js +591 -0
  3. package/dist/Atlaspack.js +656 -0
  4. package/dist/AtlaspackConfig.js +324 -0
  5. package/dist/AtlaspackConfig.schema.js +108 -0
  6. package/dist/BundleGraph.js +1628 -0
  7. package/dist/CommittedAsset.js +142 -0
  8. package/dist/Dependency.js +125 -0
  9. package/dist/Environment.js +132 -0
  10. package/dist/EnvironmentManager.js +108 -0
  11. package/dist/IdentifierRegistry.js +38 -0
  12. package/dist/InternalConfig.js +37 -0
  13. package/dist/PackagerRunner.js +531 -0
  14. package/dist/ReporterRunner.js +151 -0
  15. package/dist/RequestTracker.js +1368 -0
  16. package/dist/SymbolPropagation.js +620 -0
  17. package/dist/TargetDescriptor.schema.js +143 -0
  18. package/dist/Transformation.js +487 -0
  19. package/dist/UncommittedAsset.js +315 -0
  20. package/dist/Validation.js +196 -0
  21. package/dist/applyRuntimes.js +305 -0
  22. package/dist/assetUtils.js +168 -0
  23. package/dist/atlaspack-v3/AtlaspackV3.js +70 -0
  24. package/dist/atlaspack-v3/NapiWorkerPool.js +57 -0
  25. package/dist/atlaspack-v3/fs.js +52 -0
  26. package/dist/atlaspack-v3/index.js +25 -0
  27. package/dist/atlaspack-v3/jsCallable.js +16 -0
  28. package/dist/atlaspack-v3/worker/compat/asset-symbols.js +190 -0
  29. package/dist/atlaspack-v3/worker/compat/bitflags.js +94 -0
  30. package/dist/atlaspack-v3/worker/compat/dependency.js +43 -0
  31. package/dist/atlaspack-v3/worker/compat/environment.js +57 -0
  32. package/dist/atlaspack-v3/worker/compat/index.js +25 -0
  33. package/dist/atlaspack-v3/worker/compat/mutable-asset.js +152 -0
  34. package/dist/atlaspack-v3/worker/compat/plugin-config.js +76 -0
  35. package/dist/atlaspack-v3/worker/compat/plugin-logger.js +26 -0
  36. package/dist/atlaspack-v3/worker/compat/plugin-options.js +122 -0
  37. package/dist/atlaspack-v3/worker/compat/plugin-tracer.js +10 -0
  38. package/dist/atlaspack-v3/worker/compat/target.js +14 -0
  39. package/dist/atlaspack-v3/worker/worker.js +292 -0
  40. package/dist/constants.js +17 -0
  41. package/dist/dumpGraphToGraphViz.js +281 -0
  42. package/dist/index.js +62 -0
  43. package/dist/loadAtlaspackPlugin.js +128 -0
  44. package/dist/loadDotEnv.js +41 -0
  45. package/dist/projectPath.js +83 -0
  46. package/dist/public/Asset.js +279 -0
  47. package/dist/public/Bundle.js +224 -0
  48. package/dist/public/BundleGraph.js +359 -0
  49. package/dist/public/BundleGroup.js +53 -0
  50. package/dist/public/Config.js +286 -0
  51. package/dist/public/Dependency.js +138 -0
  52. package/dist/public/Environment.js +278 -0
  53. package/dist/public/MutableBundleGraph.js +277 -0
  54. package/dist/public/PluginOptions.js +80 -0
  55. package/dist/public/Symbols.js +248 -0
  56. package/dist/public/Target.js +69 -0
  57. package/dist/registerCoreWithSerializer.js +38 -0
  58. package/dist/requests/AssetGraphRequest.js +429 -0
  59. package/dist/requests/AssetGraphRequestRust.js +246 -0
  60. package/dist/requests/AssetRequest.js +130 -0
  61. package/dist/requests/AtlaspackBuildRequest.js +60 -0
  62. package/dist/requests/AtlaspackConfigRequest.js +490 -0
  63. package/dist/requests/BundleGraphRequest.js +441 -0
  64. package/dist/requests/ConfigRequest.js +222 -0
  65. package/dist/requests/DevDepRequest.js +204 -0
  66. package/dist/requests/EntryRequest.js +314 -0
  67. package/dist/requests/PackageRequest.js +65 -0
  68. package/dist/requests/PathRequest.js +349 -0
  69. package/dist/requests/TargetRequest.js +1310 -0
  70. package/dist/requests/ValidationRequest.js +49 -0
  71. package/dist/requests/WriteBundleRequest.js +254 -0
  72. package/dist/requests/WriteBundlesRequest.js +165 -0
  73. package/dist/requests/asset-graph-diff.js +126 -0
  74. package/dist/requests/asset-graph-dot.js +131 -0
  75. package/dist/resolveOptions.js +268 -0
  76. package/dist/rustWorkerThreadDylibHack.js +19 -0
  77. package/dist/serializerCore.browser.js +43 -0
  78. package/dist/summarizeRequest.js +39 -0
  79. package/dist/types.js +31 -0
  80. package/dist/utils.js +172 -0
  81. package/dist/worker.js +130 -0
  82. package/lib/AssetGraph.js +1 -0
  83. package/package.json +22 -22
  84. package/src/AssetGraph.ts +1 -0
  85. package/tsconfig.json +55 -2
  86. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createValidationRequest;
7
+ const nullthrows_1 = __importDefault(require("nullthrows"));
8
+ const AtlaspackConfig_1 = require("../AtlaspackConfig");
9
+ const ReporterRunner_1 = require("../ReporterRunner");
10
+ const Validation_1 = __importDefault(require("../Validation"));
11
+ const AtlaspackConfigRequest_1 = __importDefault(require("./AtlaspackConfigRequest"));
12
+ const RequestTracker_1 = require("../RequestTracker");
13
+ function createValidationRequest(input) {
14
+ return {
15
+ id: 'validation',
16
+ type: RequestTracker_1.requestTypes.validation_request,
17
+ run: async ({ input: { assetRequests, optionsRef }, api, options, farm }) => {
18
+ let { config: processedConfig, cachePath } = (0, nullthrows_1.default)(await api.runRequest((0, AtlaspackConfigRequest_1.default)()));
19
+ let config = new AtlaspackConfig_1.AtlaspackConfig(processedConfig, options);
20
+ let trackedRequestsDesc = assetRequests.filter((request) => {
21
+ // @ts-expect-error TS2345
22
+ return config.getValidatorNames(request.filePath).length > 0;
23
+ });
24
+ // Schedule validations on workers for all plugins that implement the one-asset-at-a-time "validate" method.
25
+ let promises = trackedRequestsDesc.map(async (request) => (await farm.createHandle('runValidate'))({
26
+ requests: [request],
27
+ optionsRef: optionsRef,
28
+ configCachePath: cachePath,
29
+ }));
30
+ // Skip sending validation requests if no validators were configured
31
+ if (trackedRequestsDesc.length === 0) {
32
+ return;
33
+ }
34
+ // Schedule validations on the main thread for all validation plugins that implement "validateAll".
35
+ promises.push(
36
+ // @ts-expect-error TS2345
37
+ new Validation_1.default({
38
+ requests: trackedRequestsDesc,
39
+ options,
40
+ config,
41
+ // @ts-expect-error TS2322
42
+ report: ReporterRunner_1.report,
43
+ dedicatedThread: true,
44
+ }).run());
45
+ await Promise.all(promises);
46
+ },
47
+ input,
48
+ };
49
+ }
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.default = createWriteBundleRequest;
40
+ const constants_1 = require("../constants");
41
+ const nullthrows_1 = __importDefault(require("nullthrows"));
42
+ const path_1 = __importDefault(require("path"));
43
+ const Bundle_1 = require("../public/Bundle");
44
+ const utils_1 = require("@atlaspack/utils");
45
+ const stream_1 = require("stream");
46
+ const projectPath_1 = require("../projectPath");
47
+ const AtlaspackConfigRequest_1 = __importStar(require("./AtlaspackConfigRequest"));
48
+ const PluginOptions_1 = __importDefault(require("../public/PluginOptions"));
49
+ const logger_1 = require("@atlaspack/logger");
50
+ const DevDepRequest_1 = require("./DevDepRequest");
51
+ const diagnostic_1 = __importStar(require("@atlaspack/diagnostic"));
52
+ const profiler_1 = require("@atlaspack/profiler");
53
+ const RequestTracker_1 = require("../RequestTracker");
54
+ const feature_flags_1 = require("@atlaspack/feature-flags");
55
+ const EnvironmentManager_1 = require("../EnvironmentManager");
56
+ const HASH_REF_PREFIX_LEN = constants_1.HASH_REF_PREFIX.length;
57
+ const BOUNDARY_LENGTH = constants_1.HASH_REF_PREFIX.length + 32 - 1;
58
+ /**
59
+ * Writes a bundle to the dist directory, replacing hash references with the final content hashes.
60
+ */
61
+ function createWriteBundleRequest(input) {
62
+ let name = (0, nullthrows_1.default)(input.bundle.name);
63
+ let nameHash = (0, nullthrows_1.default)(input.hashRefToNameHash.get(input.bundle.hashReference));
64
+ return {
65
+ id: `${input.bundle.id}:${input.info.hash}:${nameHash}:${name}`,
66
+ type: RequestTracker_1.requestTypes.write_bundle_request,
67
+ run,
68
+ input,
69
+ };
70
+ }
71
+ // @ts-expect-error TS7031
72
+ async function run({ input, options, api }) {
73
+ let { bundleGraph, bundle, info, hashRefToNameHash } = input;
74
+ let { inputFS, outputFS } = options;
75
+ let name = (0, nullthrows_1.default)(bundle.name);
76
+ let thisHashReference = bundle.hashReference;
77
+ if (info.type !== bundle.type) {
78
+ name = name.slice(0, -path_1.default.extname(name).length) + '.' + info.type;
79
+ }
80
+ if (name.includes(thisHashReference)) {
81
+ let thisNameHash = (0, nullthrows_1.default)(hashRefToNameHash.get(thisHashReference));
82
+ name = name.replace(thisHashReference, thisNameHash);
83
+ }
84
+ let filePath = (0, projectPath_1.joinProjectPath)(bundle.target.distDir, name);
85
+ // Watch the bundle and source map for deletion.
86
+ // Also watch the dist dir because invalidateOnFileDelete does not currently
87
+ // invalidate when a parent directory is deleted.
88
+ // TODO: do we want to also watch for file edits?
89
+ api.invalidateOnFileDelete(bundle.target.distDir);
90
+ api.invalidateOnFileDelete(filePath);
91
+ let cacheKeys = info.cacheKeys;
92
+ let mapKey = cacheKeys.map;
93
+ let fullPath = (0, projectPath_1.fromProjectPath)(options.projectRoot, filePath);
94
+ const env = (0, EnvironmentManager_1.fromEnvironmentId)(bundle.env);
95
+ if (mapKey && env.sourceMap && !env.sourceMap.inline) {
96
+ api.invalidateOnFileDelete((0, projectPath_1.toProjectPath)(options.projectRoot, fullPath + '.map'));
97
+ }
98
+ let dir = path_1.default.dirname(fullPath);
99
+ await outputFS.mkdirp(dir); // ? Got rid of dist exists, is this an expensive operation
100
+ // Use the file mode from the entry asset as the file mode for the bundle.
101
+ // Don't do this for browser builds, as the executable bit in particular is unnecessary.
102
+ let publicBundle = Bundle_1.NamedBundle.get(bundle, bundleGraph, options);
103
+ let mainEntry = publicBundle.getMainEntry();
104
+ let writeOptions = publicBundle.env.isBrowser() || !mainEntry
105
+ ? undefined
106
+ : {
107
+ mode: (await inputFS.stat(mainEntry.filePath)).mode,
108
+ };
109
+ let contentStream;
110
+ if (info.isLargeBlob) {
111
+ contentStream = options.cache.getStream(cacheKeys.content);
112
+ }
113
+ else {
114
+ contentStream = (0, utils_1.blobToStream)(await options.cache.getBlob(cacheKeys.content));
115
+ }
116
+ let size = 0;
117
+ contentStream = contentStream.pipe(
118
+ // @ts-expect-error TS2554
119
+ new utils_1.TapStream((buf) => {
120
+ size += buf.length;
121
+ }));
122
+ let configResult = (0, nullthrows_1.default)(
123
+ // @ts-expect-error TS2347
124
+ await api.runRequest((0, AtlaspackConfigRequest_1.default)()));
125
+ let config = (0, AtlaspackConfigRequest_1.getCachedAtlaspackConfig)(configResult, options);
126
+ let { devDeps, invalidDevDeps } = await (0, DevDepRequest_1.getDevDepRequests)(api);
127
+ (0, DevDepRequest_1.invalidateDevDeps)(invalidDevDeps, options, config);
128
+ await writeFiles(contentStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api);
129
+ const hasSourceMap = (0, feature_flags_1.getFeatureFlag)('cachePerformanceImprovements')
130
+ ? await options.cache.hasLargeBlob(mapKey)
131
+ : await options.cache.has(mapKey);
132
+ if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
133
+ const mapEntry = (0, feature_flags_1.getFeatureFlag)('cachePerformanceImprovements')
134
+ ? await options.cache.getLargeBlob(mapKey)
135
+ : await options.cache.getBlob(mapKey);
136
+ await writeFiles((0, utils_1.blobToStream)(mapEntry), info, hashRefToNameHash, options, config, outputFS, (0, projectPath_1.toProjectPathUnsafe)((0, projectPath_1.fromProjectPathRelative)(filePath) + '.map'), writeOptions, devDeps, api);
137
+ }
138
+ let res = {
139
+ filePath,
140
+ bundleId: bundle.id,
141
+ type: info.type,
142
+ stats: {
143
+ size,
144
+ time: info.time ?? 0,
145
+ },
146
+ };
147
+ api.storeResult(res);
148
+ return res;
149
+ }
150
+ async function writeFiles(
151
+ // @ts-expect-error TS2503
152
+ inputStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api) {
153
+ let compressors = await config.getCompressors((0, projectPath_1.fromProjectPathRelative)(filePath));
154
+ let fullPath = (0, projectPath_1.fromProjectPath)(options.projectRoot, filePath);
155
+ let stream = info.hashReferences.length
156
+ ? inputStream.pipe(replaceStream(hashRefToNameHash))
157
+ : inputStream;
158
+ let promises = [];
159
+ for (let compressor of compressors) {
160
+ promises.push(
161
+ // @ts-expect-error TS2345
162
+ runCompressor(compressor, cloneStream(stream), options, outputFS, fullPath, writeOptions, devDeps, api));
163
+ }
164
+ await Promise.all(promises);
165
+ }
166
+ async function runCompressor(compressor,
167
+ // @ts-expect-error TS2503
168
+ stream, options, outputFS, filePath, writeOptions, devDeps, api) {
169
+ let measurement;
170
+ try {
171
+ measurement = profiler_1.tracer.createMeasurement(compressor.name, 'compress', path_1.default.relative(options.projectRoot, filePath));
172
+ let res = await compressor.plugin.compress({
173
+ stream,
174
+ options: new PluginOptions_1.default(options),
175
+ logger: new logger_1.PluginLogger({ origin: compressor.name }),
176
+ tracer: new profiler_1.PluginTracer({ origin: compressor.name, category: 'compress' }),
177
+ });
178
+ if (res != null) {
179
+ await new Promise((resolve, reject) => (0, stream_1.pipeline)(res.stream, outputFS.createWriteStream(filePath + (res.type != null ? '.' + res.type : ''), writeOptions), (err) => {
180
+ if (err)
181
+ reject(err);
182
+ // @ts-expect-error TS2794
183
+ else
184
+ resolve();
185
+ }));
186
+ }
187
+ }
188
+ catch (err) {
189
+ throw new diagnostic_1.default({
190
+ diagnostic: (0, diagnostic_1.errorToDiagnostic)(err, {
191
+ origin: compressor.name,
192
+ }),
193
+ });
194
+ }
195
+ finally {
196
+ measurement && measurement.end();
197
+ // Add dev deps for compressor plugins AFTER running them, to account for lazy require().
198
+ let devDepRequest = await (0, DevDepRequest_1.createDevDependency)({
199
+ specifier: compressor.name,
200
+ resolveFrom: compressor.resolveFrom,
201
+ }, devDeps, options);
202
+ await (0, DevDepRequest_1.runDevDepRequest)(api, devDepRequest);
203
+ }
204
+ }
205
+ function replaceStream(hashRefToNameHash) {
206
+ let boundaryStr = Buffer.alloc(0);
207
+ let replaced = Buffer.alloc(0);
208
+ return new stream_1.Transform({
209
+ transform(chunk, encoding, cb) {
210
+ let str = Buffer.concat([boundaryStr, Buffer.from(chunk)]);
211
+ let lastMatchI = 0;
212
+ if (replaced.length < str.byteLength) {
213
+ replaced = Buffer.alloc(str.byteLength);
214
+ }
215
+ let replacedLength = 0;
216
+ while (lastMatchI < str.byteLength) {
217
+ let matchI = str.indexOf(constants_1.HASH_REF_PREFIX, lastMatchI);
218
+ if (matchI === -1) {
219
+ replaced.set(str.subarray(lastMatchI, str.byteLength), replacedLength);
220
+ replacedLength += str.byteLength - lastMatchI;
221
+ break;
222
+ }
223
+ else {
224
+ let match = str
225
+ .subarray(matchI, matchI + HASH_REF_PREFIX_LEN + constants_1.HASH_REF_HASH_LEN)
226
+ .toString();
227
+ let replacement = Buffer.from(hashRefToNameHash.get(match) ?? match);
228
+ replaced.set(str.subarray(lastMatchI, matchI), replacedLength);
229
+ replacedLength += matchI - lastMatchI;
230
+ replaced.set(replacement, replacedLength);
231
+ replacedLength += replacement.byteLength;
232
+ lastMatchI = matchI + HASH_REF_PREFIX_LEN + constants_1.HASH_REF_HASH_LEN;
233
+ }
234
+ }
235
+ boundaryStr = replaced.subarray(replacedLength - BOUNDARY_LENGTH, replacedLength);
236
+ let strUpToBoundary = replaced.subarray(0, replacedLength - BOUNDARY_LENGTH);
237
+ cb(null, strUpToBoundary);
238
+ },
239
+ flush(cb) {
240
+ cb(null, boundaryStr);
241
+ },
242
+ });
243
+ }
244
+ // @ts-expect-error TS2503
245
+ function cloneStream(readable) {
246
+ let res = new stream_1.Readable();
247
+ res._read = () => { };
248
+ // @ts-expect-error TS7006
249
+ readable.on('data', (chunk) => res.push(chunk));
250
+ readable.on('end', () => res.push(null));
251
+ // @ts-expect-error TS7006
252
+ readable.on('error', (err) => res.emit('error', err));
253
+ return res;
254
+ }
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createWriteBundlesRequest;
7
+ const feature_flags_1 = require("@atlaspack/feature-flags");
8
+ const RequestTracker_1 = require("../RequestTracker");
9
+ const types_1 = require("../types");
10
+ const ReporterRunner_1 = require("../ReporterRunner");
11
+ const constants_1 = require("../constants");
12
+ const projectPath_1 = require("../projectPath");
13
+ const nullthrows_1 = __importDefault(require("nullthrows"));
14
+ const rust_1 = require("@atlaspack/rust");
15
+ const PackageRequest_1 = require("./PackageRequest");
16
+ const WriteBundleRequest_1 = __importDefault(require("./WriteBundleRequest"));
17
+ function reportPackagingProgress(completeBundles, totalBundles) {
18
+ if (!(0, feature_flags_1.getFeatureFlag)('cliProgressReportingImprovements')) {
19
+ return;
20
+ }
21
+ (0, ReporterRunner_1.report)({
22
+ type: 'buildProgress',
23
+ phase: 'packagingAndOptimizing',
24
+ totalBundles,
25
+ completeBundles,
26
+ });
27
+ }
28
+ /**
29
+ * Packages, optimizes, and writes all bundles to the dist directory.
30
+ */
31
+ function createWriteBundlesRequest(input) {
32
+ return {
33
+ type: RequestTracker_1.requestTypes.write_bundles_request,
34
+ id: 'write_bundles:' + input.bundleGraph.getBundleGraphHash(),
35
+ run,
36
+ input,
37
+ };
38
+ }
39
+ async function run({ input, api, farm, options, }) {
40
+ let { bundleGraph, optionsRef } = input;
41
+ let { ref, dispose } = await farm.createSharedReference(bundleGraph);
42
+ api.invalidateOnOptionChange('shouldContentHash');
43
+ let res = new Map();
44
+ let bundleInfoMap = {};
45
+ let writeEarlyPromises = {};
46
+ let hashRefToNameHash = new Map();
47
+ // Include inline bundles so that non-inline bundles referenced from inline bundles are written to
48
+ // separate files. This ensures that source maps are written and work.
49
+ const allBundles = bundleGraph.getBundles({
50
+ includeInline: (0, feature_flags_1.getFeatureFlag)('inlineBundlesSourceMapFixes'),
51
+ });
52
+ const bundles = allBundles
53
+ .filter((bundle) => bundle.bundleBehavior !== types_1.BundleBehavior.inline &&
54
+ bundle.bundleBehavior !== types_1.BundleBehavior.inlineIsolated)
55
+ .filter((bundle) => {
56
+ // Do not package and write placeholder bundles to disk. We just
57
+ // need to update the name so other bundles can reference it.
58
+ if (bundle.isPlaceholder) {
59
+ let hash = bundle.id.slice(-8);
60
+ hashRefToNameHash.set(bundle.hashReference, hash);
61
+ let name = (0, nullthrows_1.default)(bundle.name, `Expected ${bundle.type} bundle to have a name`).replace(bundle.hashReference, hash);
62
+ res.set(bundle.id, {
63
+ filePath: (0, projectPath_1.joinProjectPath)(bundle.target.distDir, name),
64
+ bundleId: bundle.id,
65
+ type: bundle.type, // FIXME: this is wrong if the packager changes the type...
66
+ stats: {
67
+ time: 0,
68
+ size: 0,
69
+ },
70
+ });
71
+ return false;
72
+ }
73
+ return true;
74
+ });
75
+ let cachedBundles = new Set(bundles.filter((b) => api.canSkipSubrequest(bundleGraph.getHash(b))));
76
+ // Package on the main thread if there is only one bundle to package.
77
+ // This avoids the cost of serializing the bundle graph for single file change builds.
78
+ let useMainThread = bundles.length === 1 || bundles.length - cachedBundles.size <= 1;
79
+ try {
80
+ let completeBundles = cachedBundles.size;
81
+ reportPackagingProgress(completeBundles, bundles.length);
82
+ await Promise.all(bundles.map(async (bundle) => {
83
+ let request = (0, PackageRequest_1.createPackageRequest)({
84
+ bundle,
85
+ bundleGraph,
86
+ bundleGraphReference: ref,
87
+ optionsRef,
88
+ useMainThread,
89
+ });
90
+ let info = await api.runRequest(request);
91
+ if (!cachedBundles.has(bundle)) {
92
+ completeBundles++;
93
+ reportPackagingProgress(completeBundles, bundles.length);
94
+ }
95
+ if (!useMainThread) {
96
+ // Force a refresh of the cache to avoid a race condition
97
+ // between threaded reads and writes that can result in an LMDB cache miss:
98
+ // 1. The main thread has read some value from cache, necessitating a read transaction.
99
+ // 2. Concurrently, Thread A finishes a packaging request.
100
+ // 3. Subsequently, the main thread is tasked with this request, but fails because the read transaction is stale.
101
+ // This only occurs if the reading thread has a transaction that was created before the writing thread committed,
102
+ // and the transaction is still live when the reading thread attempts to get the written value.
103
+ // See https://github.com/parcel-bundler/parcel/issues/9121
104
+ options.cache.refresh();
105
+ }
106
+ bundleInfoMap[bundle.id] = info;
107
+ if (!info.hashReferences.length) {
108
+ hashRefToNameHash.set(bundle.hashReference, options.shouldContentHash
109
+ ? info.hash.slice(-8)
110
+ : bundle.id.slice(-8));
111
+ let writeBundleRequest = (0, WriteBundleRequest_1.default)({
112
+ bundle,
113
+ info,
114
+ hashRefToNameHash,
115
+ bundleGraph,
116
+ });
117
+ let promise = api.runRequest(writeBundleRequest);
118
+ // If the promise rejects before we await it (below), we don't want to crash the build.
119
+ promise.catch(() => { });
120
+ writeEarlyPromises[bundle.id] = promise;
121
+ }
122
+ }));
123
+ assignComplexNameHashes(hashRefToNameHash, bundles, bundleInfoMap, options);
124
+ await Promise.all(bundles.map((bundle) => {
125
+ let promise = writeEarlyPromises[bundle.id] ??
126
+ api.runRequest((0, WriteBundleRequest_1.default)({
127
+ bundle,
128
+ info: bundleInfoMap[bundle.id],
129
+ hashRefToNameHash,
130
+ bundleGraph,
131
+ }));
132
+ return promise.then((r) => res.set(bundle.id, r));
133
+ }));
134
+ api.storeResult(res);
135
+ return res;
136
+ }
137
+ finally {
138
+ await dispose();
139
+ }
140
+ }
141
+ function assignComplexNameHashes(hashRefToNameHash, bundles, bundleInfoMap, options) {
142
+ for (let bundle of bundles) {
143
+ if (hashRefToNameHash.get(bundle.hashReference) != null) {
144
+ continue;
145
+ }
146
+ hashRefToNameHash.set(bundle.hashReference, options.shouldContentHash
147
+ ? (0, rust_1.hashString)([...getBundlesIncludedInHash(bundle.id, bundleInfoMap)]
148
+ .map((bundleId) => bundleInfoMap[bundleId].hash)
149
+ .join(':')).slice(-8)
150
+ : bundle.id.slice(-8));
151
+ }
152
+ }
153
+ function getBundlesIncludedInHash(bundleId, bundleInfoMap, included = new Set()) {
154
+ included.add(bundleId);
155
+ for (let hashRef of bundleInfoMap[bundleId]?.hashReferences ?? []) {
156
+ let referencedId = getIdFromHashRef(hashRef);
157
+ if (!included.has(referencedId)) {
158
+ getBundlesIncludedInHash(referencedId, bundleInfoMap, included);
159
+ }
160
+ }
161
+ return included;
162
+ }
163
+ function getIdFromHashRef(hashRef) {
164
+ return hashRef.slice(constants_1.HASH_REF_PREFIX.length);
165
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /* eslint-disable no-console */
7
+ // @ts-expect-error missing types
8
+ const default_1 = __importDefault(require("rfdc/default"));
9
+ const jest_diff_1 = require("jest-diff");
10
+ const projectPath_1 = require("../projectPath");
11
+ function filterNode(node) {
12
+ let clone = (0, default_1.default)(node);
13
+ // Clean up anything you don't want to see in the diff
14
+ // delete clone.id;
15
+ delete clone.value.id;
16
+ delete clone.value.meta.id;
17
+ delete clone.value.sourceAssetId;
18
+ delete clone.value.env.id;
19
+ delete clone.value.isEsm;
20
+ delete clone.value.shouldWrap;
21
+ delete clone.value.contentKey;
22
+ delete clone.value.placeholder;
23
+ delete clone.value.code;
24
+ delete clone.value.hasCjsExports;
25
+ delete clone.value.staticExports;
26
+ delete clone.value.isConstantModule;
27
+ delete clone.value.hasNodeReplacements;
28
+ delete clone.value.stats;
29
+ delete clone.value.astKey;
30
+ delete clone.value.astGenerator;
31
+ delete clone.value.dependencies;
32
+ return clone;
33
+ }
34
+ // @ts-expect-error missing return type
35
+ function compactDeep(obj, ignoredPatterns = [], currentPath = '$') {
36
+ if (obj instanceof Map) {
37
+ const copy = {};
38
+ Array.from(obj.entries()).forEach(([k, v]) => {
39
+ if (v != null) {
40
+ copy[k] = compactDeep(v, ignoredPatterns, `${currentPath}.${k}`);
41
+ }
42
+ });
43
+ return copy;
44
+ }
45
+ else if (Array.isArray(obj)) {
46
+ // @ts-expect-error implicit any
47
+ return obj.map((v) => compactDeep(v, ignoredPatterns, `${currentPath}[]`));
48
+ }
49
+ else if (typeof obj === 'object') {
50
+ const copy = {};
51
+ Object.entries(obj ?? {}).forEach(([key, value]) => {
52
+ const path = `${currentPath}.${key}`;
53
+ if (ignoredPatterns.some((pattern) => path.includes(pattern))) {
54
+ return;
55
+ }
56
+ // Equivalent false == null
57
+ if (key === 'isWeak' && value === false) {
58
+ return;
59
+ }
60
+ if (value != null) {
61
+ copy[key] = compactDeep(value, ignoredPatterns, path);
62
+ }
63
+ });
64
+ return copy;
65
+ }
66
+ else if (obj != null) {
67
+ return obj;
68
+ }
69
+ }
70
+ function assetGraphDiff(jsAssetGraph, rustAssetGraph) {
71
+ const getNodes = (graph) => {
72
+ let nodes = {};
73
+ // @ts-expect-error implicit any
74
+ graph.traverse((nodeId) => {
75
+ let node = graph.getNode(nodeId) ?? null;
76
+ if (!node)
77
+ return;
78
+ if (node.type === 'dependency') {
79
+ let sourcePath = node.value.sourcePath ?? (0, projectPath_1.toProjectPath)('', 'entry');
80
+ nodes[`dep:${(0, projectPath_1.fromProjectPathRelative)(sourcePath)}:${node.value.specifier}`] = filterNode(node);
81
+ }
82
+ else if (node.type === 'asset') {
83
+ nodes[`asset:${(0, projectPath_1.fromProjectPathRelative)(node.value.filePath)}`] =
84
+ filterNode(node);
85
+ }
86
+ });
87
+ return nodes;
88
+ };
89
+ const jsNodes = getNodes(jsAssetGraph);
90
+ const rustNodes = getNodes(rustAssetGraph);
91
+ const all = new Set([...Object.keys(jsNodes), ...Object.keys(rustNodes)]);
92
+ const missing = [];
93
+ const extra = [];
94
+ for (const key of all.keys()) {
95
+ if (process.env.NATIVE_COMPARE !== 'true') {
96
+ continue;
97
+ }
98
+ let jsNode = jsNodes[key];
99
+ let rustNode = rustNodes[key];
100
+ if (!rustNode) {
101
+ missing.push(key);
102
+ continue;
103
+ }
104
+ if (!jsNode) {
105
+ extra.push(key);
106
+ continue;
107
+ }
108
+ console.log(key);
109
+ const ignoredPatterns = [
110
+ // ignored because we don't copy the environment ID back from rust
111
+ // in the target value
112
+ '$.value.target.env.id',
113
+ // ignore asset.mapKey because we don't do persistence on rust yet
114
+ '$.value.mapKey',
115
+ // ignore this because it's just the output hash. We don't need to compute
116
+ // this yet
117
+ '$.value.outputHash',
118
+ // ignore correspondingRequest from all nodes
119
+ '$.correspondingRequest',
120
+ ];
121
+ console.log((0, jest_diff_1.diff)(compactDeep(jsNode, ignoredPatterns), compactDeep(rustNode, ignoredPatterns)));
122
+ }
123
+ console.log('Missing', missing);
124
+ console.log('Extra', extra);
125
+ }
126
+ module.exports = assetGraphDiff;