UNPKG

10.8 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _events = _interopRequireDefault(require("events"));
9
10var _nullthrows = _interopRequireDefault(require("nullthrows"));
11
12var _path = _interopRequireDefault(require("path"));
13
14var _utils = require("@parcel/utils");
15
16var _AssetGraph = _interopRequireDefault(require("./AssetGraph"));
17
18var _RequestTracker = _interopRequireWildcard(require("./RequestTracker"));
19
20var _constants = require("./constants");
21
22var _requests = require("./requests");
23
24var _dumpGraphToGraphViz = _interopRequireDefault(require("./dumpGraphToGraphViz"));
25
26function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
27
28function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
30function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
32function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
33
34const requestPriorities = [['entry_request'], ['target_request'], ['dep_path_request', 'asset_request']];
35
36class AssetGraphBuilder extends _events.default {
37 constructor(...args) {
38 super(...args);
39
40 _defineProperty(this, "assetGraph", void 0);
41
42 _defineProperty(this, "requestGraph", void 0);
43
44 _defineProperty(this, "requestTracker", void 0);
45
46 _defineProperty(this, "entryRequestRunner", void 0);
47
48 _defineProperty(this, "targetRequestRunner", void 0);
49
50 _defineProperty(this, "depPathRequestRunner", void 0);
51
52 _defineProperty(this, "assetRequestRunner", void 0);
53
54 _defineProperty(this, "assetRequests", void 0);
55
56 _defineProperty(this, "runValidate", void 0);
57
58 _defineProperty(this, "queue", void 0);
59
60 _defineProperty(this, "changedAssets", new Map());
61
62 _defineProperty(this, "options", void 0);
63
64 _defineProperty(this, "config", void 0);
65
66 _defineProperty(this, "workerFarm", void 0);
67
68 _defineProperty(this, "cacheKey", void 0);
69
70 _defineProperty(this, "handle", void 0);
71 }
72
73 async init({
74 config,
75 options,
76 entries,
77 name,
78 assetRequests,
79 workerFarm
80 }) {
81 this.options = options;
82 this.assetRequests = [];
83 let {
84 minify,
85 hot,
86 scopeHoist
87 } = options;
88 this.cacheKey = (0, _utils.md5FromObject)({
89 parcelVersion: _constants.PARCEL_VERSION,
90 name,
91 options: {
92 minify,
93 hot,
94 scopeHoist
95 },
96 entries
97 });
98 this.queue = new _utils.PromiseQueue();
99 this.runValidate = workerFarm.createHandle('runValidate');
100 this.handle = workerFarm.createReverseHandle(() => {// Do nothing, this is here because there is a bug in `@parcel/workers`
101 });
102 let changes = await this.readFromCache();
103
104 if (!changes) {
105 this.assetGraph = new _AssetGraph.default();
106 this.requestGraph = new _RequestTracker.RequestGraph();
107 }
108
109 this.assetGraph.initOptions({
110 onNodeRemoved: node => this.handleNodeRemovedFromAssetGraph(node),
111 onIncompleteNode: node => this.handleIncompleteNode(node)
112 });
113 let assetGraph = this.assetGraph;
114 this.requestTracker = new _RequestTracker.default({
115 graph: this.requestGraph
116 });
117 let tracker = this.requestTracker;
118 this.entryRequestRunner = new _requests.EntryRequestRunner({
119 tracker,
120 options,
121 assetGraph
122 });
123 this.targetRequestRunner = new _requests.TargetRequestRunner({
124 tracker,
125 options,
126 assetGraph
127 });
128 this.assetRequestRunner = new _requests.AssetRequestRunner({
129 tracker,
130 options,
131 workerFarm,
132 assetGraph
133 });
134 this.depPathRequestRunner = new _requests.DepPathRequestRunner({
135 tracker,
136 options,
137 config,
138 assetGraph
139 });
140
141 if (changes) {
142 this.requestGraph.invalidateUnpredictableNodes();
143 this.requestTracker.respondToFSEvents(changes);
144 } else {
145 this.assetGraph.initialize({
146 entries,
147 assetGroups: assetRequests
148 });
149 }
150 }
151
152 async build(signal) {
153 let lastQueueError;
154
155 for (let currPriorities of requestPriorities) {
156 if (!this.requestTracker.hasInvalidRequests()) {
157 break;
158 }
159
160 let promises = [];
161
162 for (let request of this.requestTracker.getInvalidRequests()) {
163 // $FlowFixMe
164 if (currPriorities.includes(request.type)) {
165 promises.push(this.runRequest(request, {
166 signal
167 }));
168 }
169 }
170
171 await Promise.all(promises);
172
173 if (lastQueueError) {
174 throw lastQueueError;
175 }
176
177 this.queue.run().catch(e => {
178 lastQueueError = e;
179 });
180 }
181
182 if (this.assetGraph.hasIncompleteNodes()) {
183 for (let id of this.assetGraph.incompleteNodeIds) {
184 this.processIncompleteAssetGraphNode((0, _nullthrows.default)(this.assetGraph.getNode(id)), signal);
185 }
186
187 await this.queue.run();
188 }
189
190 (0, _dumpGraphToGraphViz.default)(this.assetGraph, 'AssetGraph');
191 (0, _dumpGraphToGraphViz.default)(this.requestGraph, 'RequestGraph');
192 let changedAssets = this.changedAssets;
193 this.changedAssets = new Map();
194 return {
195 assetGraph: this.assetGraph,
196 changedAssets: changedAssets
197 };
198 }
199
200 async validate() {
201 let promises = this.assetRequests.map(request => this.runValidate({
202 request,
203 options: this.options
204 }));
205 this.assetRequests = [];
206 await Promise.all(promises);
207 }
208
209 async runRequest(request, runOpts) {
210 switch (request.type) {
211 case 'entry_request':
212 return this.entryRequestRunner.runRequest(request.request, runOpts);
213
214 case 'target_request':
215 return this.targetRequestRunner.runRequest(request.request, runOpts);
216
217 case 'dep_path_request':
218 return this.depPathRequestRunner.runRequest(request.request, runOpts);
219
220 case 'asset_request':
221 {
222 this.assetRequests.push(request.request);
223 let result = await this.assetRequestRunner.runRequest(request.request, runOpts);
224
225 if (result != null) {
226 for (let asset of result.assets) {
227 this.changedAssets.set(asset.id, asset); // ? Is this right?
228 }
229 }
230
231 return result;
232 }
233 }
234 }
235
236 getCorrespondingRequest(node) {
237 switch (node.type) {
238 case 'entry_specifier':
239 {
240 let type = 'entry_request';
241 return {
242 type,
243 request: node.value,
244 id: (0, _RequestTracker.generateRequestId)(type, node.value)
245 };
246 }
247
248 case 'entry_file':
249 {
250 let type = 'target_request';
251 return {
252 type,
253 request: node.value,
254 id: (0, _RequestTracker.generateRequestId)(type, node.value)
255 };
256 }
257
258 case 'dependency':
259 {
260 let type = 'dep_path_request';
261 return {
262 type,
263 request: node.value,
264 id: (0, _RequestTracker.generateRequestId)(type, node.value)
265 };
266 }
267
268 case 'asset_group':
269 {
270 let type = 'asset_request';
271 return {
272 type,
273 request: node.value,
274 id: (0, _RequestTracker.generateRequestId)(type, node.value)
275 };
276 }
277 }
278 }
279
280 processIncompleteAssetGraphNode(node, signal) {
281 let request = (0, _nullthrows.default)(this.getCorrespondingRequest(node));
282
283 if (!this.requestTracker.isTracked(request.id)) {
284 this.queue.add(() => this.runRequest(request, {
285 signal
286 })).catch(() => {// Do nothing, the individual promise is not being awaited, but the queue is and will throw
287 });
288 }
289 }
290
291 handleIncompleteNode(node) {
292 this.processIncompleteAssetGraphNode(node);
293 }
294
295 handleNodeRemovedFromAssetGraph(node) {
296 let request = this.getCorrespondingRequest(node);
297
298 if (request != null) {
299 this.requestTracker.untrackRequest(request.id);
300 }
301 }
302
303 respondToFSEvents(events) {
304 return this.requestGraph.respondToFSEvents(events);
305 }
306
307 getWatcherOptions() {
308 let vcsDirs = ['.git', '.hg'].map(dir => _path.default.join(this.options.projectRoot, dir));
309 let ignore = [this.options.cacheDir, ...vcsDirs];
310 return {
311 ignore
312 };
313 }
314
315 getCacheKeys() {
316 let assetGraphKey = (0, _utils.md5FromString)(`${this.cacheKey}:assetGraph`);
317 let requestGraphKey = (0, _utils.md5FromString)(`${this.cacheKey}:requestGraph`);
318 let snapshotKey = (0, _utils.md5FromString)(`${this.cacheKey}:snapshot`);
319 return {
320 assetGraphKey,
321 requestGraphKey,
322 snapshotKey
323 };
324 }
325
326 async readFromCache() {
327 if (this.options.disableCache) {
328 return null;
329 }
330
331 let {
332 assetGraphKey,
333 requestGraphKey,
334 snapshotKey
335 } = this.getCacheKeys();
336 let assetGraph = await this.options.cache.get(assetGraphKey);
337 let requestGraph = await this.options.cache.get(requestGraphKey);
338
339 if (assetGraph && requestGraph) {
340 this.assetGraph = assetGraph;
341 this.requestGraph = requestGraph;
342 let opts = this.getWatcherOptions();
343
344 let snapshotPath = this.options.cache._getCachePath(snapshotKey, '.txt');
345
346 return this.options.inputFS.getEventsSince(this.options.projectRoot, snapshotPath, opts);
347 }
348
349 return null;
350 }
351
352 async writeToCache() {
353 if (this.options.disableCache) {
354 return;
355 }
356
357 let {
358 assetGraphKey,
359 requestGraphKey,
360 snapshotKey
361 } = this.getCacheKeys();
362 await this.options.cache.set(assetGraphKey, this.assetGraph);
363 await this.options.cache.set(requestGraphKey, this.requestGraph);
364 let opts = this.getWatcherOptions();
365
366 let snapshotPath = this.options.cache._getCachePath(snapshotKey, '.txt');
367
368 await this.options.inputFS.writeSnapshot(this.options.projectRoot, snapshotPath, opts);
369 }
370
371}
372
373exports.default = AssetGraphBuilder;
\No newline at end of file