1 | 'use strict';
|
2 |
|
3 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
4 |
|
5 | const builtins = require('./builtins');
|
6 | const path = require('path');
|
7 | const glob = require('glob');
|
8 | const fs = require('./utils/fs');
|
9 |
|
10 | const EMPTY_SHIM = require.resolve('./builtins/_empty');
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | class Resolver {
|
26 | constructor(options = {}) {
|
27 | this.options = options;
|
28 | this.cache = new Map();
|
29 | this.packageCache = new Map();
|
30 | this.rootPackage = null;
|
31 | }
|
32 |
|
33 | resolve(input, parent) {
|
34 | var _this = this;
|
35 |
|
36 | return _asyncToGenerator(function* () {
|
37 | let filename = input;
|
38 |
|
39 |
|
40 | let key = _this.getCacheKey(filename, parent);
|
41 | if (_this.cache.has(key)) {
|
42 | return _this.cache.get(key);
|
43 | }
|
44 |
|
45 |
|
46 | if (/[*+{}]/.test(filename) && glob.hasMagic(filename)) {
|
47 | return { path: path.resolve(path.dirname(parent), filename) };
|
48 | }
|
49 |
|
50 |
|
51 | let extensions = Array.isArray(_this.options.extensions) ? _this.options.extensions.slice() : Object.keys(_this.options.extensions);
|
52 |
|
53 | if (parent) {
|
54 |
|
55 | const parentExt = path.extname(parent);
|
56 | extensions = [parentExt, ...extensions.filter(function (ext) {
|
57 | return ext !== parentExt;
|
58 | })];
|
59 | }
|
60 |
|
61 | extensions.unshift('');
|
62 |
|
63 | let dir = parent ? path.dirname(parent) : process.cwd();
|
64 |
|
65 |
|
66 | if (parent) {
|
67 | filename = _this.resolveFilename(filename, dir);
|
68 | }
|
69 |
|
70 |
|
71 | filename = yield _this.loadAlias(filename, dir);
|
72 |
|
73 | let resolved;
|
74 | if (path.isAbsolute(filename)) {
|
75 |
|
76 | resolved = yield _this.loadRelative(filename, extensions);
|
77 | } else {
|
78 |
|
79 | resolved = yield _this.loadNodeModules(filename, dir, extensions);
|
80 | }
|
81 |
|
82 | if (!resolved) {
|
83 | let err = new Error("Cannot find module '" + input + "' from '" + dir + "'");
|
84 | err.code = 'MODULE_NOT_FOUND';
|
85 | throw err;
|
86 | }
|
87 |
|
88 | _this.cache.set(key, resolved);
|
89 | return resolved;
|
90 | })();
|
91 | }
|
92 |
|
93 | getCacheKey(filename, parent) {
|
94 | return (parent ? path.dirname(parent) : '') + ':' + filename;
|
95 | }
|
96 |
|
97 | resolveFilename(filename, dir) {
|
98 | switch (filename[0]) {
|
99 | case '/':
|
100 |
|
101 | return path.resolve(this.options.rootDir, filename.slice(1));
|
102 |
|
103 | case '~':
|
104 |
|
105 |
|
106 | while (dir !== this.options.rootDir && path.basename(path.dirname(dir)) !== 'node_modules') {
|
107 | dir = path.dirname(dir);
|
108 | }
|
109 |
|
110 | return path.join(dir, filename.slice(1));
|
111 |
|
112 | case '.':
|
113 |
|
114 | return path.resolve(dir, filename);
|
115 |
|
116 | default:
|
117 |
|
118 | return path.normalize(filename);
|
119 | }
|
120 | }
|
121 |
|
122 | loadRelative(filename, extensions) {
|
123 | var _this2 = this;
|
124 |
|
125 | return _asyncToGenerator(function* () {
|
126 |
|
127 | let pkg = yield _this2.findPackage(path.dirname(filename));
|
128 |
|
129 |
|
130 | return (yield _this2.loadAsFile(filename, extensions, pkg)) || (yield _this2.loadDirectory(filename, extensions, pkg));
|
131 | })();
|
132 | }
|
133 |
|
134 | loadNodeModules(filename, dir, extensions) {
|
135 | var _this3 = this;
|
136 |
|
137 | return _asyncToGenerator(function* () {
|
138 |
|
139 | if (builtins[filename]) {
|
140 | return { path: builtins[filename] };
|
141 | }
|
142 |
|
143 | let parts = _this3.getModuleParts(filename);
|
144 | let root = path.parse(dir).root;
|
145 |
|
146 | while (dir !== root) {
|
147 |
|
148 | if (path.basename(dir) === 'node_modules') {
|
149 | dir = path.dirname(dir);
|
150 | }
|
151 |
|
152 | try {
|
153 |
|
154 | let moduleDir = path.join(dir, 'node_modules', parts[0]);
|
155 | let stats = yield fs.stat(moduleDir);
|
156 | if (stats.isDirectory()) {
|
157 | let f = path.join(dir, 'node_modules', filename);
|
158 |
|
159 |
|
160 |
|
161 | if (parts.length > 1) {
|
162 | let pkg = yield _this3.readPackage(moduleDir);
|
163 | let res = yield _this3.loadAsFile(f, extensions, pkg);
|
164 | if (res) {
|
165 | return res;
|
166 | }
|
167 | }
|
168 |
|
169 |
|
170 | return yield _this3.loadDirectory(f, extensions);
|
171 | }
|
172 | } catch (err) {}
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | dir = path.dirname(dir);
|
178 | }
|
179 | })();
|
180 | }
|
181 |
|
182 | isFile(file) {
|
183 | return _asyncToGenerator(function* () {
|
184 | try {
|
185 | let stat = yield fs.stat(file);
|
186 | return stat.isFile() || stat.isFIFO();
|
187 | } catch (err) {
|
188 | return false;
|
189 | }
|
190 | })();
|
191 | }
|
192 |
|
193 | loadDirectory(dir, extensions, pkg) {
|
194 | var _this4 = this;
|
195 |
|
196 | return _asyncToGenerator(function* () {
|
197 | try {
|
198 | pkg = yield _this4.readPackage(dir);
|
199 |
|
200 |
|
201 | let main = _this4.getPackageMain(pkg);
|
202 | let res = (yield _this4.loadAsFile(main, extensions, pkg)) || (yield _this4.loadDirectory(main, extensions, pkg));
|
203 |
|
204 | if (res) {
|
205 | return res;
|
206 | }
|
207 | } catch (err) {}
|
208 |
|
209 |
|
210 |
|
211 |
|
212 | return yield _this4.loadAsFile(path.join(dir, 'index'), extensions, pkg);
|
213 | })();
|
214 | }
|
215 |
|
216 | readPackage(dir) {
|
217 | var _this5 = this;
|
218 |
|
219 | return _asyncToGenerator(function* () {
|
220 | let file = path.join(dir, 'package.json');
|
221 | if (_this5.packageCache.has(file)) {
|
222 | return _this5.packageCache.get(file);
|
223 | }
|
224 |
|
225 | let json = yield fs.readFile(file, 'utf8');
|
226 | let pkg = JSON.parse(json);
|
227 |
|
228 | pkg.pkgfile = file;
|
229 | pkg.pkgdir = dir;
|
230 |
|
231 | _this5.packageCache.set(file, pkg);
|
232 | return pkg;
|
233 | })();
|
234 | }
|
235 |
|
236 | getPackageMain(pkg) {
|
237 |
|
238 |
|
239 | let main = [pkg.module, pkg['jsnext:main'], pkg.browser, pkg.main].find(entry => typeof entry === 'string');
|
240 |
|
241 |
|
242 | if (!main || main === '.' || main === './') {
|
243 | main = 'index';
|
244 | }
|
245 |
|
246 | return path.resolve(pkg.pkgdir, main);
|
247 | }
|
248 |
|
249 | loadAsFile(file, extensions, pkg) {
|
250 | var _this6 = this;
|
251 |
|
252 | return _asyncToGenerator(function* () {
|
253 |
|
254 | var _iteratorNormalCompletion = true;
|
255 | var _didIteratorError = false;
|
256 | var _iteratorError = undefined;
|
257 |
|
258 | try {
|
259 | for (var _iterator = _this6.expandFile(file, extensions, pkg)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
260 | let f = _step.value;
|
261 |
|
262 | if (yield _this6.isFile(f)) {
|
263 | return { path: f, pkg };
|
264 | }
|
265 | }
|
266 | } catch (err) {
|
267 | _didIteratorError = true;
|
268 | _iteratorError = err;
|
269 | } finally {
|
270 | try {
|
271 | if (!_iteratorNormalCompletion && _iterator.return) {
|
272 | _iterator.return();
|
273 | }
|
274 | } finally {
|
275 | if (_didIteratorError) {
|
276 | throw _iteratorError;
|
277 | }
|
278 | }
|
279 | }
|
280 | })();
|
281 | }
|
282 |
|
283 | expandFile(file, extensions, pkg, expandAliases = true) {
|
284 |
|
285 | let res = [];
|
286 | var _iteratorNormalCompletion2 = true;
|
287 | var _didIteratorError2 = false;
|
288 | var _iteratorError2 = undefined;
|
289 |
|
290 | try {
|
291 | for (var _iterator2 = extensions[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
292 | let ext = _step2.value;
|
293 |
|
294 | let f = file + ext;
|
295 |
|
296 | if (expandAliases) {
|
297 | let alias = this.resolveAliases(file + ext, pkg);
|
298 | if (alias !== f) {
|
299 | res = res.concat(this.expandFile(alias, extensions, pkg, false));
|
300 | }
|
301 | }
|
302 |
|
303 | res.push(f);
|
304 | }
|
305 | } catch (err) {
|
306 | _didIteratorError2 = true;
|
307 | _iteratorError2 = err;
|
308 | } finally {
|
309 | try {
|
310 | if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
311 | _iterator2.return();
|
312 | }
|
313 | } finally {
|
314 | if (_didIteratorError2) {
|
315 | throw _iteratorError2;
|
316 | }
|
317 | }
|
318 | }
|
319 |
|
320 | return res;
|
321 | }
|
322 |
|
323 | resolveAliases(filename, pkg) {
|
324 |
|
325 | return this.resolvePackageAliases(this.resolvePackageAliases(filename, pkg), this.rootPackage);
|
326 | }
|
327 |
|
328 | resolvePackageAliases(filename, pkg) {
|
329 |
|
330 | if (pkg) {
|
331 | return this.getAlias(filename, pkg.pkgdir, pkg.alias) || this.getAlias(filename, pkg.pkgdir, pkg.browser) || filename;
|
332 | }
|
333 |
|
334 | return filename;
|
335 | }
|
336 |
|
337 | getAlias(filename, dir, aliases) {
|
338 | if (!filename || !aliases || typeof aliases !== 'object') {
|
339 | return null;
|
340 | }
|
341 |
|
342 | let alias;
|
343 |
|
344 |
|
345 | if (path.isAbsolute(filename)) {
|
346 | filename = path.relative(dir, filename);
|
347 | if (filename[0] !== '.') {
|
348 | filename = './' + filename;
|
349 | }
|
350 |
|
351 | alias = aliases[filename];
|
352 | } else {
|
353 |
|
354 | alias = aliases[filename];
|
355 | if (alias == null) {
|
356 |
|
357 | let parts = this.getModuleParts(filename);
|
358 | alias = aliases[parts[0]];
|
359 | if (typeof alias === 'string') {
|
360 |
|
361 | alias = path.join(alias, ...parts.slice(1));
|
362 | }
|
363 | }
|
364 | }
|
365 |
|
366 |
|
367 | if (alias === false) {
|
368 | return EMPTY_SHIM;
|
369 | }
|
370 |
|
371 |
|
372 |
|
373 | if (alias && alias[0] === '.') {
|
374 | return path.resolve(dir, alias);
|
375 | }
|
376 |
|
377 |
|
378 | return alias;
|
379 | }
|
380 |
|
381 | findPackage(dir) {
|
382 | var _this7 = this;
|
383 |
|
384 | return _asyncToGenerator(function* () {
|
385 |
|
386 | let root = path.parse(dir).root;
|
387 | while (dir !== root && path.basename(dir) !== 'node_modules') {
|
388 | try {
|
389 | return yield _this7.readPackage(dir);
|
390 | } catch (err) {
|
391 |
|
392 | }
|
393 |
|
394 | dir = path.dirname(dir);
|
395 | }
|
396 | })();
|
397 | }
|
398 |
|
399 | loadAlias(filename, dir) {
|
400 | var _this8 = this;
|
401 |
|
402 | return _asyncToGenerator(function* () {
|
403 |
|
404 | if (!_this8.rootPackage) {
|
405 | _this8.rootPackage = yield _this8.findPackage(_this8.options.rootDir);
|
406 | }
|
407 |
|
408 |
|
409 | let pkg = yield _this8.findPackage(dir);
|
410 | return _this8.resolveAliases(filename, pkg);
|
411 | })();
|
412 | }
|
413 |
|
414 | getModuleParts(name) {
|
415 | let parts = path.normalize(name).split(path.sep);
|
416 | if (parts[0].charAt(0) === '@') {
|
417 |
|
418 | parts.splice(0, 2, `${parts[0]}/${parts[1]}`);
|
419 | }
|
420 |
|
421 | return parts;
|
422 | }
|
423 | }
|
424 |
|
425 | module.exports = Resolver; |
\ | No newline at end of file |