source: frontend/node_modules/enhanced-resolve/lib/SymlinkPlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const forEachBail = require("./forEachBail");
9const { getPathsCached } = require("./getPaths");
10const { PathType, getType } = require("./util/path");
11
12/** @typedef {import("./Resolver")} Resolver */
13/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
14/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
15
16module.exports = class SymlinkPlugin {
17 /**
18 * @param {string | ResolveStepHook} source source
19 * @param {string | ResolveStepHook} target target
20 */
21 constructor(source, target) {
22 this.source = source;
23 this.target = target;
24 }
25
26 /**
27 * @param {Resolver} resolver the resolver
28 * @returns {void}
29 */
30 apply(resolver) {
31 const target = resolver.ensureHook(this.target);
32 const fs = resolver.fileSystem;
33 resolver
34 .getHook(this.source)
35 .tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
36 if (request.ignoreSymlinks) return callback();
37 const pathsResult = getPathsCached(
38 fs,
39 /** @type {string} */ (request.path),
40 );
41 const { paths, segments } = pathsResult;
42 // `pathsResult.segments` is shared across callers via the cache.
43 // The only place we need to mutate is `pathSegments[idx] = result`
44 // when `fs.readlink` succeeds — which is rare (the vast majority
45 // of paths contain no symlinks, e.g. every resolve on
46 // `cache-predicate`'s no-symlink fixture). Defer the copy until
47 // we actually see a symlink so the common no-symlink path stays
48 // allocation-free.
49 /** @type {string[] | null} */
50 let pathSegments = null;
51
52 let containsSymlink = false;
53 let idx = -1;
54 forEachBail(
55 paths,
56 /**
57 * @param {string} path path
58 * @param {(err?: null | Error, result?: null | number) => void} callback callback
59 * @returns {void}
60 */
61 (path, callback) => {
62 idx++;
63 if (resolveContext.fileDependencies) {
64 resolveContext.fileDependencies.add(path);
65 }
66 fs.readlink(path, (err, result) => {
67 if (!err && result) {
68 // First symlink seen — take our own copy now, so
69 // the cached `segments` array stays pristine for
70 // sibling resolves.
71 if (pathSegments === null) {
72 pathSegments = [...segments];
73 }
74 pathSegments[idx] = /** @type {string} */ (result);
75 containsSymlink = true;
76 // Shortcut when absolute symlink found
77 const resultType = getType(result.toString());
78 if (
79 resultType === PathType.AbsoluteWin ||
80 resultType === PathType.AbsolutePosix
81 ) {
82 return callback(null, idx);
83 }
84 }
85 callback();
86 });
87 },
88 /**
89 * @param {null | Error=} err error
90 * @param {null | number=} idx result
91 * @returns {void}
92 */
93 (err, idx) => {
94 if (!containsSymlink) return callback();
95 // `containsSymlink === true` implies we took a copy in
96 // `pathSegments` already, so it's non-null. The copy is
97 // our own, so `slice` to trim is fine and spreading to
98 // "unshare" is no longer necessary.
99 const own = /** @type {string[]} */ (pathSegments);
100 const resultSegments =
101 typeof idx === "number" ? own.slice(0, idx + 1) : own;
102 const result = resultSegments.reduceRight((a, b) =>
103 resolver.join(a, b),
104 );
105 /** @type {ResolveRequest} */
106 const obj = {
107 ...request,
108 path: result,
109 };
110 resolver.doResolve(
111 target,
112 obj,
113 `resolved symlink to ${result}`,
114 resolveContext,
115 callback,
116 );
117 },
118 );
119 });
120 }
121};
Note: See TracBrowser for help on using the repository browser.