UNPKG

10.4 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.DepPathRequestRunner = exports.AssetRequestRunner = exports.TargetRequestRunner = exports.EntryRequestRunner = void 0;
7
8var _assert = _interopRequireDefault(require("assert"));
9
10var _nullthrows = _interopRequireDefault(require("nullthrows"));
11
12var _utils = require("@parcel/utils");
13
14var _AssetGraph = require("./AssetGraph");
15
16var _ResolverRunner = _interopRequireDefault(require("./ResolverRunner"));
17
18var _EntryResolver = require("./EntryResolver");
19
20var _TargetResolver = _interopRequireDefault(require("./TargetResolver"));
21
22var _RequestTracker = require("./RequestTracker");
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26function _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; }
27
28class EntryRequestRunner extends _RequestTracker.RequestRunner {
29 constructor(opts) {
30 super(opts);
31
32 _defineProperty(this, "entryResolver", void 0);
33
34 _defineProperty(this, "assetGraph", void 0);
35
36 this.type = 'entry_request';
37 this.entryResolver = new _EntryResolver.EntryResolver(opts.options);
38 this.assetGraph = opts.assetGraph;
39 }
40
41 run(request) {
42 return this.entryResolver.resolveEntry(request);
43 }
44
45 onComplete(request, result, api) {
46 this.assetGraph.resolveEntry(request, result.entries); // Connect files like package.json that affect the entry
47 // resolution so we invalidate when they change.
48
49 for (let file of result.files) {
50 api.invalidateOnFileUpdate(file.filePath);
51 } // If the entry specifier is a glob, add a glob node so
52 // we invalidate when a new file matches.
53
54
55 if ((0, _utils.isGlob)(request)) {
56 api.invalidateOnFileCreate(request);
57 }
58 }
59
60}
61
62exports.EntryRequestRunner = EntryRequestRunner;
63
64class TargetRequestRunner extends _RequestTracker.RequestRunner {
65 constructor(opts) {
66 super(opts);
67
68 _defineProperty(this, "targetResolver", void 0);
69
70 _defineProperty(this, "assetGraph", void 0);
71
72 this.type = 'target_request';
73 this.targetResolver = new _TargetResolver.default(opts.options);
74 this.assetGraph = opts.assetGraph;
75 }
76
77 run(request) {
78 return this.targetResolver.resolve(request.packagePath);
79 }
80
81 onComplete(request, result, api) {
82 this.assetGraph.resolveTargets(request, result.targets); // Connect files like package.json that affect the target
83 // resolution so we invalidate when they change.
84
85 for (let file of result.files) {
86 api.invalidateOnFileUpdate(file.filePath);
87 }
88 }
89
90}
91
92exports.TargetRequestRunner = TargetRequestRunner;
93
94class AssetRequestRunner extends _RequestTracker.RequestRunner {
95 constructor(opts) {
96 super(opts);
97
98 _defineProperty(this, "options", void 0);
99
100 _defineProperty(this, "runTransform", void 0);
101
102 _defineProperty(this, "assetGraph", void 0);
103
104 this.type = 'asset_request';
105 this.options = opts.options;
106 this.runTransform = opts.workerFarm.createHandle('runTransform');
107 this.assetGraph = opts.assetGraph;
108 }
109
110 async run(request, api) {
111 api.invalidateOnFileUpdate((await this.options.inputFS.realpath(request.filePath)));
112 let start = Date.now();
113 let {
114 assets,
115 configRequests
116 } = await this.runTransform({
117 request: request,
118 options: this.options
119 });
120 let time = Date.now() - start;
121
122 for (let asset of assets) {
123 asset.stats.time = time;
124 }
125
126 return {
127 assets,
128 configRequests
129 };
130 }
131
132 onComplete(request, result, api) {
133 this.assetGraph.resolveAssetGroup(request, result.assets);
134 let {
135 assets,
136 configRequests
137 } = result;
138
139 for (let asset of assets) {
140 for (let filePath of asset.includedFiles.keys()) {
141 api.invalidateOnFileUpdate(filePath);
142 api.invalidateOnFileDelete(filePath);
143 }
144 } // TODO: this should no longer be needed once we have ConfigRequestRunner
145
146
147 let graph = this.tracker.graph;
148 let subrequestNodes = []; // Add config requests
149
150 for (let {
151 request,
152 result
153 } of configRequests) {
154 let id = (0, _RequestTracker.generateRequestId)('config_request', request);
155 let shouldSetupInvalidations = graph.invalidNodeIds.has(id) || !graph.hasNode(id);
156 let subrequestNode = (0, _nullthrows.default)(graph.addRequest({
157 id,
158 type: 'config_request',
159 request,
160 result
161 }));
162 (0, _assert.default)(subrequestNode.type === 'request');
163
164 if (shouldSetupInvalidations) {
165 if (result.resolvedPath != null) {
166 graph.invalidateOnFileUpdate(subrequestNode.id, result.resolvedPath);
167 }
168
169 for (let filePath of result.includedFiles) {
170 graph.invalidateOnFileUpdate(subrequestNode.id, filePath);
171 }
172
173 if (result.watchGlob != null) {
174 graph.invalidateOnFileCreate(subrequestNode.id, result.watchGlob);
175 }
176
177 if (result.shouldInvalidateOnStartup) {
178 graph.invalidateOnStartup(subrequestNode.id);
179 }
180 }
181
182 subrequestNodes.push(subrequestNode); // Add dep version requests
183
184 for (let [moduleSpecifier, version] of result.devDeps) {
185 let depVersionRequst = {
186 moduleSpecifier,
187 resolveFrom: result.resolvedPath // TODO: resolveFrom should be nearest package boundary
188
189 };
190 let id = (0, _RequestTracker.generateRequestId)('dep_version_request', depVersionRequst);
191 let shouldSetupInvalidations = graph.invalidNodeIds.has(id) || !graph.hasNode(id);
192 let subrequestNode = (0, _nullthrows.default)(graph.addRequest({
193 id,
194 type: 'dep_version_request',
195 request: depVersionRequst,
196 result: version
197 }));
198 (0, _assert.default)(subrequestNode.type === 'request');
199
200 if (shouldSetupInvalidations) {
201 if (this.options.lockFile != null) {
202 graph.invalidateOnFileUpdate(subrequestNode.id, this.options.lockFile);
203 }
204 }
205
206 subrequestNodes.push(subrequestNode);
207 }
208 }
209
210 api.replaceSubrequests(subrequestNodes); // TODO: add includedFiles even if it failed so we can try a rebuild if those files change
211 }
212
213}
214
215exports.AssetRequestRunner = AssetRequestRunner;
216
217const invertMap = map => new Map([...map].map(([key, val]) => [val, key]));
218
219class DepPathRequestRunner extends _RequestTracker.RequestRunner {
220 constructor(opts) {
221 super(opts);
222
223 _defineProperty(this, "resolverRunner", void 0);
224
225 _defineProperty(this, "assetGraph", void 0);
226
227 this.type = 'dep_path_request';
228 let {
229 options,
230 config,
231 assetGraph
232 } = opts;
233 this.resolverRunner = new _ResolverRunner.default({
234 options,
235 config
236 });
237 this.assetGraph = assetGraph;
238 }
239
240 run(request) {
241 return this.resolverRunner.resolve(request);
242 }
243
244 onComplete(request, result, api) {
245 let dependency = request;
246 let assetGroup = result;
247
248 if (!assetGroup) {
249 this.assetGraph.resolveDependency(dependency, null);
250 return;
251 }
252
253 let defer = this.shouldDeferDependency(dependency, assetGroup.sideEffects);
254 dependency.isDeferred = defer;
255 let assetGroupNode = (0, _AssetGraph.nodeFromAssetGroup)(assetGroup, defer);
256 let existingAssetGroupNode = this.assetGraph.getNode(assetGroupNode.id);
257
258 if (existingAssetGroupNode) {
259 // Don't overwrite non-deferred asset groups with deferred ones
260 (0, _assert.default)(existingAssetGroupNode.type === 'asset_group');
261 assetGroupNode.deferred = existingAssetGroupNode.deferred && defer;
262 }
263
264 this.assetGraph.resolveDependency(dependency, assetGroupNode);
265
266 if (existingAssetGroupNode) {
267 // Node already existed, that asset might have deferred dependencies,
268 // recheck all dependencies of all assets of this asset group
269 this.assetGraph.traverse((node, parent, actions) => {
270 if (node == assetGroupNode) {
271 return;
272 }
273
274 if (node.type === 'dependency' && !node.value.isDeferred) {
275 actions.skipChildren();
276 return;
277 }
278
279 if (node.type == 'asset_group') {
280 (0, _assert.default)(parent && parent.type === 'dependency');
281
282 if (node.deferred && !this.shouldDeferDependency(parent.value, node.value.sideEffects)) {
283 parent.value.isDeferred = false;
284 node.deferred = false;
285 this.assetGraph.markIncomplete(node);
286 }
287
288 actions.skipChildren();
289 }
290
291 return node;
292 }, assetGroupNode);
293 } // ? Should this happen if asset is deferred?
294
295
296 api.invalidateOnFileDelete(assetGroup.filePath); // TODO: invalidate dep path requests that have failed and a file creation may fulfill the request
297 } // Defer transforming this dependency if it is marked as weak, there are no side effects,
298 // no re-exported symbols are used by ancestor dependencies and the re-exporting asset isn't
299 // using a wildcard.
300 // This helps with performance building large libraries like `lodash-es`, which re-exports
301 // a huge number of functions since we can avoid even transforming the files that aren't used.
302
303
304 shouldDeferDependency(dependency, sideEffects) {
305 let defer = false;
306
307 if (dependency.isWeak && sideEffects === false && !dependency.symbols.has('*') && !dependency.env.isLibrary // TODO (T-232): improve the logic below and remove this.
308 ) {
309 let depNode = this.assetGraph.getNode(dependency.id);
310 (0, _assert.default)(depNode);
311 let assets = this.assetGraph.getNodesConnectedTo(depNode);
312 let symbols = invertMap(dependency.symbols);
313 (0, _assert.default)(assets.length === 1);
314 let firstAsset = assets[0];
315 (0, _assert.default)(firstAsset.type === 'asset');
316 let resolvedAsset = firstAsset.value;
317 let deps = this.assetGraph.getIncomingDependencies(resolvedAsset);
318 defer = deps.every(d => !d.symbols.has('*') && ![...d.symbols.keys()].some(symbol => {
319 let assetSymbol = resolvedAsset.symbols.get(symbol);
320 return assetSymbol != null && symbols.has(assetSymbol);
321 }));
322 }
323
324 return defer;
325 }
326
327}
328
329exports.DepPathRequestRunner = DepPathRequestRunner;
\No newline at end of file