source: frontend/node_modules/enhanced-resolve/lib/SelfReferencePlugin.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.1 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 DescriptionFileUtils = require("./DescriptionFileUtils");
9
10/** @typedef {import("./Resolver")} Resolver */
11/** @typedef {import("./Resolver").JsonObject} JsonObject */
12/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
13/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
14
15const slashCode = "/".charCodeAt(0);
16
17// Sentinel stored in `_nameCache` when the description file either has no
18// exports field (so self-reference can't apply) or no string `name`.
19const NO_SELF_REF = Symbol("NoSelfRef");
20
21module.exports = class SelfReferencePlugin {
22 /**
23 * @param {string | ResolveStepHook} source source
24 * @param {string | string[]} fieldNamePath name path
25 * @param {string | ResolveStepHook} target target
26 */
27 constructor(source, fieldNamePath, target) {
28 this.source = source;
29 this.target = target;
30 this.fieldName = fieldNamePath;
31 // Self-reference needs both an exports field and a `"name"` string.
32 // Both are stable per description-file content, so cache the decision
33 // in one WeakMap: the resolved name when self-reference is possible,
34 // or `NO_SELF_REF` when it isn't. This skips the two per-resolve
35 // `DescriptionFileUtils.getField` walks for hot packages.
36 /** @type {WeakMap<JsonObject, string | typeof NO_SELF_REF>} */
37 this._nameCache = new WeakMap();
38 }
39
40 /**
41 * @param {Resolver} resolver the resolver
42 * @returns {void}
43 */
44 apply(resolver) {
45 const target = resolver.ensureHook(this.target);
46 resolver
47 .getHook(this.source)
48 .tapAsync("SelfReferencePlugin", (request, resolveContext, callback) => {
49 if (!request.descriptionFileData) return callback();
50
51 const req = request.request;
52 if (!req) return callback();
53
54 const { descriptionFileData } = request;
55 let name = this._nameCache.get(descriptionFileData);
56 if (name === undefined) {
57 // Feature is only enabled when an exports field is present
58 const exportsField = DescriptionFileUtils.getField(
59 descriptionFileData,
60 this.fieldName,
61 );
62 if (!exportsField) {
63 this._nameCache.set(descriptionFileData, NO_SELF_REF);
64 return callback();
65 }
66 const rawName = DescriptionFileUtils.getField(
67 descriptionFileData,
68 "name",
69 );
70 if (typeof rawName !== "string") {
71 this._nameCache.set(descriptionFileData, NO_SELF_REF);
72 return callback();
73 }
74 name = rawName;
75 this._nameCache.set(descriptionFileData, name);
76 } else if (name === NO_SELF_REF) {
77 return callback();
78 }
79
80 if (
81 req.startsWith(name) &&
82 (req.length === name.length ||
83 req.charCodeAt(name.length) === slashCode)
84 ) {
85 const remainingRequest = `.${req.slice(name.length)}`;
86 /** @type {ResolveRequest} */
87 const obj = {
88 ...request,
89 request: remainingRequest,
90 path: /** @type {string} */ (request.descriptionFileRoot),
91 relativePath: ".",
92 };
93
94 resolver.doResolve(
95 target,
96 obj,
97 "self reference",
98 resolveContext,
99 callback,
100 );
101 } else {
102 return callback();
103 }
104 });
105 }
106};
Note: See TracBrowser for help on using the repository browser.