source: trip-planner-front/node_modules/webpack/lib/ContextModuleFactory.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const asyncLib = require("neo-async");
9const { AsyncSeriesWaterfallHook, SyncWaterfallHook } = require("tapable");
10const ContextModule = require("./ContextModule");
11const ModuleFactory = require("./ModuleFactory");
12const ContextElementDependency = require("./dependencies/ContextElementDependency");
13const LazySet = require("./util/LazySet");
14const { cachedSetProperty } = require("./util/cleverMerge");
15const { createFakeHook } = require("./util/deprecation");
16const { join } = require("./util/fs");
17
18/** @typedef {import("./ContextModule").ContextModuleOptions} ContextModuleOptions */
19/** @typedef {import("./ContextModule").ResolveDependenciesCallback} ResolveDependenciesCallback */
20/** @typedef {import("./Module")} Module */
21/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
22/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
23/** @typedef {import("./ResolverFactory")} ResolverFactory */
24/** @typedef {import("./dependencies/ContextDependency")} ContextDependency */
25/** @template T @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T> */
26/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
27
28const EMPTY_RESOLVE_OPTIONS = {};
29
30module.exports = class ContextModuleFactory extends ModuleFactory {
31 /**
32 * @param {ResolverFactory} resolverFactory resolverFactory
33 */
34 constructor(resolverFactory) {
35 super();
36 /** @type {AsyncSeriesWaterfallHook<[TODO[], ContextModuleOptions]>} */
37 const alternativeRequests = new AsyncSeriesWaterfallHook([
38 "modules",
39 "options"
40 ]);
41 this.hooks = Object.freeze({
42 /** @type {AsyncSeriesWaterfallHook<[TODO]>} */
43 beforeResolve: new AsyncSeriesWaterfallHook(["data"]),
44 /** @type {AsyncSeriesWaterfallHook<[TODO]>} */
45 afterResolve: new AsyncSeriesWaterfallHook(["data"]),
46 /** @type {SyncWaterfallHook<[string[]]>} */
47 contextModuleFiles: new SyncWaterfallHook(["files"]),
48 /** @type {FakeHook<Pick<AsyncSeriesWaterfallHook<[TODO[]]>, "tap" | "tapAsync" | "tapPromise" | "name">>} */
49 alternatives: createFakeHook(
50 {
51 name: "alternatives",
52 /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["intercept"]} */
53 intercept: interceptor => {
54 throw new Error(
55 "Intercepting fake hook ContextModuleFactory.hooks.alternatives is not possible, use ContextModuleFactory.hooks.alternativeRequests instead"
56 );
57 },
58 /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tap"]} */
59 tap: (options, fn) => {
60 alternativeRequests.tap(options, fn);
61 },
62 /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tapAsync"]} */
63 tapAsync: (options, fn) => {
64 alternativeRequests.tapAsync(options, (items, _options, callback) =>
65 fn(items, callback)
66 );
67 },
68 /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tapPromise"]} */
69 tapPromise: (options, fn) => {
70 alternativeRequests.tapPromise(options, fn);
71 }
72 },
73 "ContextModuleFactory.hooks.alternatives has deprecated in favor of ContextModuleFactory.hooks.alternativeRequests with an additional options argument.",
74 "DEP_WEBPACK_CONTEXT_MODULE_FACTORY_ALTERNATIVES"
75 ),
76 alternativeRequests
77 });
78 this.resolverFactory = resolverFactory;
79 }
80
81 /**
82 * @param {ModuleFactoryCreateData} data data object
83 * @param {function(Error=, ModuleFactoryResult=): void} callback callback
84 * @returns {void}
85 */
86 create(data, callback) {
87 const context = data.context;
88 const dependencies = data.dependencies;
89 const resolveOptions = data.resolveOptions;
90 const dependency = /** @type {ContextDependency} */ (dependencies[0]);
91 const fileDependencies = new LazySet();
92 const missingDependencies = new LazySet();
93 const contextDependencies = new LazySet();
94 this.hooks.beforeResolve.callAsync(
95 {
96 context: context,
97 dependencies: dependencies,
98 resolveOptions,
99 fileDependencies,
100 missingDependencies,
101 contextDependencies,
102 ...dependency.options
103 },
104 (err, beforeResolveResult) => {
105 if (err) {
106 return callback(err, {
107 fileDependencies,
108 missingDependencies,
109 contextDependencies
110 });
111 }
112
113 // Ignored
114 if (!beforeResolveResult) {
115 return callback(null, {
116 fileDependencies,
117 missingDependencies,
118 contextDependencies
119 });
120 }
121
122 const context = beforeResolveResult.context;
123 const request = beforeResolveResult.request;
124 const resolveOptions = beforeResolveResult.resolveOptions;
125
126 let loaders,
127 resource,
128 loadersPrefix = "";
129 const idx = request.lastIndexOf("!");
130 if (idx >= 0) {
131 let loadersRequest = request.substr(0, idx + 1);
132 let i;
133 for (
134 i = 0;
135 i < loadersRequest.length && loadersRequest[i] === "!";
136 i++
137 ) {
138 loadersPrefix += "!";
139 }
140 loadersRequest = loadersRequest
141 .substr(i)
142 .replace(/!+$/, "")
143 .replace(/!!+/g, "!");
144 if (loadersRequest === "") {
145 loaders = [];
146 } else {
147 loaders = loadersRequest.split("!");
148 }
149 resource = request.substr(idx + 1);
150 } else {
151 loaders = [];
152 resource = request;
153 }
154
155 const contextResolver = this.resolverFactory.get(
156 "context",
157 dependencies.length > 0
158 ? cachedSetProperty(
159 resolveOptions || EMPTY_RESOLVE_OPTIONS,
160 "dependencyType",
161 dependencies[0].category
162 )
163 : resolveOptions
164 );
165 const loaderResolver = this.resolverFactory.get("loader");
166
167 asyncLib.parallel(
168 [
169 callback => {
170 contextResolver.resolve(
171 {},
172 context,
173 resource,
174 {
175 fileDependencies,
176 missingDependencies,
177 contextDependencies
178 },
179 (err, result) => {
180 if (err) return callback(err);
181 callback(null, result);
182 }
183 );
184 },
185 callback => {
186 asyncLib.map(
187 loaders,
188 (loader, callback) => {
189 loaderResolver.resolve(
190 {},
191 context,
192 loader,
193 {
194 fileDependencies,
195 missingDependencies,
196 contextDependencies
197 },
198 (err, result) => {
199 if (err) return callback(err);
200 callback(null, result);
201 }
202 );
203 },
204 callback
205 );
206 }
207 ],
208 (err, result) => {
209 if (err) {
210 return callback(err, {
211 fileDependencies,
212 missingDependencies,
213 contextDependencies
214 });
215 }
216
217 this.hooks.afterResolve.callAsync(
218 {
219 addon:
220 loadersPrefix +
221 result[1].join("!") +
222 (result[1].length > 0 ? "!" : ""),
223 resource: result[0],
224 resolveDependencies: this.resolveDependencies.bind(this),
225 ...beforeResolveResult
226 },
227 (err, result) => {
228 if (err) {
229 return callback(err, {
230 fileDependencies,
231 missingDependencies,
232 contextDependencies
233 });
234 }
235
236 // Ignored
237 if (!result) {
238 return callback(null, {
239 fileDependencies,
240 missingDependencies,
241 contextDependencies
242 });
243 }
244
245 return callback(null, {
246 module: new ContextModule(result.resolveDependencies, result),
247 fileDependencies,
248 missingDependencies,
249 contextDependencies
250 });
251 }
252 );
253 }
254 );
255 }
256 );
257 }
258
259 /**
260 * @param {InputFileSystem} fs file system
261 * @param {ContextModuleOptions} options options
262 * @param {ResolveDependenciesCallback} callback callback function
263 * @returns {void}
264 */
265 resolveDependencies(fs, options, callback) {
266 const cmf = this;
267 const {
268 resource,
269 resourceQuery,
270 resourceFragment,
271 recursive,
272 regExp,
273 include,
274 exclude,
275 referencedExports,
276 category,
277 typePrefix
278 } = options;
279 if (!regExp || !resource) return callback(null, []);
280
281 const addDirectoryChecked = (directory, visited, callback) => {
282 fs.realpath(directory, (err, realPath) => {
283 if (err) return callback(err);
284 if (visited.has(realPath)) return callback(null, []);
285 let recursionStack;
286 addDirectory(
287 directory,
288 (dir, callback) => {
289 if (recursionStack === undefined) {
290 recursionStack = new Set(visited);
291 recursionStack.add(realPath);
292 }
293 addDirectoryChecked(dir, recursionStack, callback);
294 },
295 callback
296 );
297 });
298 };
299
300 const addDirectory = (directory, addSubDirectory, callback) => {
301 fs.readdir(directory, (err, files) => {
302 if (err) return callback(err);
303 const processedFiles = cmf.hooks.contextModuleFiles.call(
304 /** @type {string[]} */ (files).map(file => file.normalize("NFC"))
305 );
306 if (!processedFiles || processedFiles.length === 0)
307 return callback(null, []);
308 asyncLib.map(
309 processedFiles.filter(p => p.indexOf(".") !== 0),
310 (segment, callback) => {
311 const subResource = join(fs, directory, segment);
312
313 if (!exclude || !subResource.match(exclude)) {
314 fs.stat(subResource, (err, stat) => {
315 if (err) {
316 if (err.code === "ENOENT") {
317 // ENOENT is ok here because the file may have been deleted between
318 // the readdir and stat calls.
319 return callback();
320 } else {
321 return callback(err);
322 }
323 }
324
325 if (stat.isDirectory()) {
326 if (!recursive) return callback();
327 addSubDirectory(subResource, callback);
328 } else if (
329 stat.isFile() &&
330 (!include || subResource.match(include))
331 ) {
332 const obj = {
333 context: resource,
334 request:
335 "." +
336 subResource.substr(resource.length).replace(/\\/g, "/")
337 };
338
339 this.hooks.alternativeRequests.callAsync(
340 [obj],
341 options,
342 (err, alternatives) => {
343 if (err) return callback(err);
344 alternatives = alternatives
345 .filter(obj => regExp.test(obj.request))
346 .map(obj => {
347 const dep = new ContextElementDependency(
348 obj.request + resourceQuery + resourceFragment,
349 obj.request,
350 typePrefix,
351 category,
352 referencedExports
353 );
354 dep.optional = true;
355 return dep;
356 });
357 callback(null, alternatives);
358 }
359 );
360 } else {
361 callback();
362 }
363 });
364 } else {
365 callback();
366 }
367 },
368 (err, result) => {
369 if (err) return callback(err);
370
371 if (!result) return callback(null, []);
372
373 const flattenedResult = [];
374
375 for (const item of result) {
376 if (item) flattenedResult.push(...item);
377 }
378
379 callback(null, flattenedResult);
380 }
381 );
382 });
383 };
384
385 if (typeof fs.realpath === "function") {
386 addDirectoryChecked(resource, new Set(), callback);
387 } else {
388 const addSubDirectory = (dir, callback) =>
389 addDirectory(dir, addSubDirectory, callback);
390 addDirectory(resource, addSubDirectory, callback);
391 }
392 }
393};
Note: See TracBrowser for help on using the repository browser.