first commit

This commit is contained in:
monjack
2025-06-20 18:01:48 +08:00
commit 6daa6d65c1
24611 changed files with 2512443 additions and 0 deletions

20
app_vue/node_modules/enhanced-resolve/LICENSE generated vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

183
app_vue/node_modules/enhanced-resolve/README.md generated vendored Normal file
View File

@ -0,0 +1,183 @@
# enhanced-resolve
[![npm][npm]][npm-url]
[![Build Status][build-status]][build-status-url]
[![codecov][codecov-badge]][codecov-url]
[![Install Size][size]][size-url]
[![GitHub Discussions][discussion]][discussion-url]
Offers an async require.resolve function. It's highly configurable.
## Features
- plugin system
- provide a custom filesystem
- sync and async node.js filesystems included
## Getting Started
### Install
```sh
# npm
npm install enhanced-resolve
# or Yarn
yarn add enhanced-resolve
```
### Resolve
There is a Node.js API which allows to resolve requests according to the Node.js resolving rules.
Sync and async APIs are offered. A `create` method allows to create a custom resolve function.
```js
const resolve = require("enhanced-resolve");
resolve("/some/path/to/folder", "module/dir", (err, result) => {
result; // === "/some/path/node_modules/module/dir/index.js"
});
resolve.sync("/some/path/to/folder", "../../dir");
// === "/some/path/dir/index.js"
const myResolve = resolve.create({
// or resolve.create.sync
extensions: [".ts", ".js"]
// see more options below
});
myResolve("/some/path/to/folder", "ts-module", (err, result) => {
result; // === "/some/node_modules/ts-module/index.ts"
});
```
### Creating a Resolver
The easiest way to create a resolver is to use the `createResolver` function on `ResolveFactory`, along with one of the supplied File System implementations.
```js
const fs = require("fs");
const { CachedInputFileSystem, ResolverFactory } = require("enhanced-resolve");
// create a resolver
const myResolver = ResolverFactory.createResolver({
// Typical usage will consume the `fs` + `CachedInputFileSystem`, which wraps Node.js `fs` to add caching.
fileSystem: new CachedInputFileSystem(fs, 4000),
extensions: [".js", ".json"]
/* any other resolver options here. Options/defaults can be seen below */
});
// resolve a file with the new resolver
const context = {};
const lookupStartPath = "/Users/webpack/some/root/dir";
const request = "./path/to-look-up.js";
const resolveContext = {};
myResolver.resolve(context, lookupStartPath, request, resolveContext, (
err /*Error*/,
filepath /*string*/
) => {
// Do something with the path
});
```
#### Resolver Options
| Field | Default | Description |
|------------------|-----------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias | [] | A list of module alias configurations or an object which maps key to value |
| aliasFields | [] | A list of alias fields in description files |
| extensionAlias | {} | An object which maps extension to extension aliases |
| cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. |
| cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key |
| conditionNames | [] | A list of exports field condition names |
| descriptionFiles | ["package.json"] | A list of description files to read from |
| enforceExtension | false | Enforce that a extension from extensions must be used |
| exportsFields | ["exports"] | A list of exports fields in description files |
| extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files |
| fallback | [] | Same as `alias`, but only used if default resolving fails |
| fileSystem | | The file system which should be used |
| fullySpecified | false | Request passed to resolve is already fully specified and extensions or main files are not resolved for it (they are still resolved for internal requests) |
| mainFields | ["main"] | A list of main fields in description files |
| mainFiles | ["index"] | A list of main files in directories |
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name |
| plugins | [] | A list of additional resolve plugins which should be applied |
| resolver | undefined | A prepared Resolver to which the plugins are attached |
| resolveToContext | false | Resolve to a context instead of a file |
| preferRelative | false | Prefer to resolve module requests as relative request and fallback to resolving as module |
| preferAbsolute | false | Prefer to resolve server-relative urls as absolute paths before falling back to resolve in roots |
| restrictions | [] | A list of resolve restrictions |
| roots | [] | A list of root paths |
| symlinks | true | Whether to resolve symlinks to their symlinked location |
| unsafeCache | false | Use this cache object to unsafely cache the successful requests |
## Plugins
Similar to `webpack`, the core of `enhanced-resolve` functionality is implemented as individual plugins that are executed using [`tapable`](https://github.com/webpack/tapable).
These plugins can extend the functionality of the library, adding other ways for files/contexts to be resolved.
A plugin should be a `class` (or its ES5 equivalent) with an `apply` method. The `apply` method will receive a `resolver` instance, that can be used to hook in to the event system.
### Plugin Boilerplate
```js
class MyResolverPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("MyResolverPlugin", (request, resolveContext, callback) => {
// Any logic you need to create a new `request` can go here
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
}
```
Plugins are executed in a pipeline, and register which event they should be executed before/after. In the example above, `source` is the name of the event that starts the pipeline, and `target` is what event this plugin should fire, which is what continues the execution of the pipeline. For an example of how these different plugin events create a chain, see `lib/ResolverFactory.js`, in the `//// pipeline ////` section.
## Escaping
It's allowed to escape `#` as `\0#` to avoid parsing it as fragment.
enhanced-resolve will try to resolve requests containing `#` as path and as fragment, so it will automatically figure out if `./some#thing` means `.../some.js#thing` or `.../some#thing.js`. When a `#` is resolved as path it will be escaped in the result. Here: `.../some\0#thing.js`.
## Tests
```javascript
yarn test
```
## Passing options from webpack
If you are using `webpack`, and you want to pass custom options to `enhanced-resolve`, the options are passed from the `resolve` key of your webpack configuration e.g.:
```
resolve: {
extensions: ['.js', '.jsx'],
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
plugins: [new DirectoryNamedWebpackPlugin()]
...
},
```
## License
Copyright (c) 2012-2019 JS Foundation and other contributors
MIT (http://www.opensource.org/licenses/mit-license.php)
[npm]: https://img.shields.io/npm/v/enhanced-resolve.svg
[npm-url]: https://www.npmjs.com/package/enhanced-resolve
[build-status]: https://github.com/webpack/enhanced-resolve/actions/workflows/test.yml/badge.svg
[build-status-url]: https://github.com/webpack/enhanced-resolve/actions
[codecov-badge]: https://codecov.io/gh/webpack/enhanced-resolve/branch/main/graph/badge.svg?token=6B6NxtsZc3
[codecov-url]: https://codecov.io/gh/webpack/enhanced-resolve
[size]: https://packagephobia.com/badge?p=enhanced-resolve
[size-url]: https://packagephobia.com/result?p=enhanced-resolve
[discussion]: https://img.shields.io/github/discussions/webpack/webpack
[discussion-url]: https://github.com/webpack/webpack/discussions

View File

@ -0,0 +1,108 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
const getInnerRequest = require("./getInnerRequest");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonPrimitive} JsonPrimitive */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class AliasFieldPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | Array<string>} field field
* @param {string | ResolveStepHook} target target
*/
constructor(source, field, target) {
this.source = source;
this.field = field;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("AliasFieldPlugin", (request, resolveContext, callback) => {
if (!request.descriptionFileData) return callback();
const innerRequest = getInnerRequest(resolver, request);
if (!innerRequest) return callback();
const fieldData = DescriptionFileUtils.getField(
request.descriptionFileData,
this.field
);
if (fieldData === null || typeof fieldData !== "object") {
if (resolveContext.log)
resolveContext.log(
"Field '" +
this.field +
"' doesn't contain a valid alias configuration"
);
return callback();
}
/** @type {JsonPrimitive | undefined} */
const data = Object.prototype.hasOwnProperty.call(
fieldData,
innerRequest
)
? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[
innerRequest
]
: innerRequest.startsWith("./")
? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[
innerRequest.slice(2)
]
: undefined;
if (data === innerRequest) return callback();
if (data === undefined) return callback();
if (data === false) {
/** @type {ResolveRequest} */
const ignoreObj = {
...request,
path: false
};
if (typeof resolveContext.yield === "function") {
resolveContext.yield(ignoreObj);
return callback(null, null);
}
return callback(null, ignoreObj);
}
/** @type {ResolveRequest} */
const obj = {
...request,
path: /** @type {string} */ (request.descriptionFileRoot),
request: /** @type {string} */ (data),
fullySpecified: false
};
resolver.doResolve(
target,
obj,
"aliased from description file " +
request.descriptionFilePath +
" with mapping '" +
innerRequest +
"' to '" +
/** @type {string} */ (data) +
"'",
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow other aliasing or raw request
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
});
}
};

View File

@ -0,0 +1,183 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
const { PathType, getType } = require("./util/path");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {string | Array<string> | false} Alias */
/** @typedef {{alias: Alias, name: string, onlyModule?: boolean}} AliasOption */
module.exports = class AliasPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {AliasOption | Array<AliasOption>} options options
* @param {string | ResolveStepHook} target target
*/
constructor(source, options, target) {
this.source = source;
this.options = Array.isArray(options) ? options : [options];
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
/**
* @param {string} maybeAbsolutePath path
* @returns {null|string} absolute path with slash ending
*/
const getAbsolutePathWithSlashEnding = maybeAbsolutePath => {
const type = getType(maybeAbsolutePath);
if (type === PathType.AbsolutePosix || type === PathType.AbsoluteWin) {
return resolver.join(maybeAbsolutePath, "_").slice(0, -1);
}
return null;
};
/**
* @param {string} path path
* @param {string} maybeSubPath sub path
* @returns {boolean} true, if path is sub path
*/
const isSubPath = (path, maybeSubPath) => {
const absolutePath = getAbsolutePathWithSlashEnding(maybeSubPath);
if (!absolutePath) return false;
return path.startsWith(absolutePath);
};
resolver
.getHook(this.source)
.tapAsync("AliasPlugin", (request, resolveContext, callback) => {
const innerRequest = request.request || request.path;
if (!innerRequest) return callback();
forEachBail(
this.options,
(item, callback) => {
/** @type {boolean} */
let shouldStop = false;
const matchRequest =
innerRequest === item.name ||
(!item.onlyModule &&
(request.request
? innerRequest.startsWith(`${item.name}/`)
: isSubPath(innerRequest, item.name)));
const splitName = item.name.split("*");
const matchWildcard = !item.onlyModule && splitName.length === 2;
if (matchRequest || matchWildcard) {
/**
* @param {Alias} alias alias
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @returns {void}
*/
const resolveWithAlias = (alias, callback) => {
if (alias === false) {
/** @type {ResolveRequest} */
const ignoreObj = {
...request,
path: false
};
if (typeof resolveContext.yield === "function") {
resolveContext.yield(ignoreObj);
return callback(null, null);
}
return callback(null, ignoreObj);
}
let newRequestStr;
const [prefix, suffix] = splitName;
if (
matchWildcard &&
innerRequest.startsWith(prefix) &&
innerRequest.endsWith(suffix)
) {
const match = innerRequest.slice(
prefix.length,
innerRequest.length - suffix.length
);
newRequestStr = item.alias.toString().replace("*", match);
}
if (
matchRequest &&
innerRequest !== alias &&
!innerRequest.startsWith(alias + "/")
) {
/** @type {string} */
const remainingRequest = innerRequest.slice(item.name.length);
newRequestStr = alias + remainingRequest;
}
if (newRequestStr !== undefined) {
shouldStop = true;
/** @type {ResolveRequest} */
const obj = {
...request,
request: newRequestStr,
fullySpecified: false
};
return resolver.doResolve(
target,
obj,
"aliased with mapping '" +
item.name +
"': '" +
alias +
"' to '" +
newRequestStr +
"'",
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
return callback();
}
);
}
return callback();
};
/**
* @param {null|Error} [err] error
* @param {null|ResolveRequest} [result] result
* @returns {void}
*/
const stoppingCallback = (err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
// Don't allow other aliasing or raw request
if (shouldStop) return callback(null, null);
return callback();
};
if (Array.isArray(item.alias)) {
return forEachBail(
item.alias,
resolveWithAlias,
stoppingCallback
);
} else {
return resolveWithAlias(item.alias, stoppingCallback);
}
}
return callback();
},
callback
);
});
}
};

View File

@ -0,0 +1,49 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class AppendPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string} appending appending
* @param {string | ResolveStepHook} target target
*/
constructor(source, appending, target) {
this.source = source;
this.appending = appending;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("AppendPlugin", (request, resolveContext, callback) => {
/** @type {ResolveRequest} */
const obj = {
...request,
path: request.path + this.appending,
relativePath:
request.relativePath && request.relativePath + this.appending
};
resolver.doResolve(
target,
obj,
this.appending,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,664 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const nextTick = require("process").nextTick;
/** @typedef {import("./Resolver").FileSystem} FileSystem */
/** @typedef {import("./Resolver").PathLike} PathLike */
/** @typedef {import("./Resolver").PathOrFileDescriptor} PathOrFileDescriptor */
/** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */
/** @typedef {FileSystem & SyncFileSystem} BaseFileSystem */
/**
* @template T
* @typedef {import("./Resolver").FileSystemCallback<T>} FileSystemCallback<T>
*/
/**
* @param {string} path path
* @returns {string} dirname
*/
const dirname = path => {
let idx = path.length - 1;
while (idx >= 0) {
const c = path.charCodeAt(idx);
// slash or backslash
if (c === 47 || c === 92) break;
idx--;
}
if (idx < 0) return "";
return path.slice(0, idx);
};
/**
* @template T
* @param {FileSystemCallback<T>[]} callbacks callbacks
* @param {Error | null} err error
* @param {T} result result
*/
const runCallbacks = (callbacks, err, result) => {
if (callbacks.length === 1) {
callbacks[0](err, result);
callbacks.length = 0;
return;
}
let error;
for (const callback of callbacks) {
try {
callback(err, result);
} catch (e) {
if (!error) error = e;
}
}
callbacks.length = 0;
if (error) throw error;
};
class OperationMergerBackend {
/**
* @param {Function | undefined} provider async method in filesystem
* @param {Function | undefined} syncProvider sync method in filesystem
* @param {BaseFileSystem} providerContext call context for the provider methods
*/
constructor(provider, syncProvider, providerContext) {
this._provider = provider;
this._syncProvider = syncProvider;
this._providerContext = providerContext;
this._activeAsyncOperations = new Map();
this.provide = this._provider
? /**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {object | FileSystemCallback<any> | undefined} options options
* @param {FileSystemCallback<any>=} callback callback
* @returns {any} result
*/
(path, options, callback) => {
if (typeof options === "function") {
callback = /** @type {FileSystemCallback<any>} */ (options);
options = undefined;
}
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
/** @type {Function} */
(callback)(
new TypeError("path must be a string, Buffer, URL or number")
);
return;
}
if (options) {
return /** @type {Function} */ (this._provider).call(
this._providerContext,
path,
options,
callback
);
}
let callbacks = this._activeAsyncOperations.get(path);
if (callbacks) {
callbacks.push(callback);
return;
}
this._activeAsyncOperations.set(path, (callbacks = [callback]));
/** @type {Function} */
(provider)(
path,
/**
* @param {Error} err error
* @param {any} result result
*/
(err, result) => {
this._activeAsyncOperations.delete(path);
runCallbacks(callbacks, err, result);
}
);
}
: null;
this.provideSync = this._syncProvider
? /**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {object=} options options
* @returns {any} result
*/
(path, options) => {
return /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path,
options
);
}
: null;
}
purge() {}
purgeParent() {}
}
/*
IDLE:
insert data: goto SYNC
SYNC:
before provide: run ticks
event loop tick: goto ASYNC_ACTIVE
ASYNC:
timeout: run tick, goto ASYNC_PASSIVE
ASYNC_PASSIVE:
before provide: run ticks
IDLE --[insert data]--> SYNC --[event loop tick]--> ASYNC_ACTIVE --[interval tick]-> ASYNC_PASSIVE
^ |
+---------[insert data]-------+
*/
const STORAGE_MODE_IDLE = 0;
const STORAGE_MODE_SYNC = 1;
const STORAGE_MODE_ASYNC = 2;
/**
* @callback Provide
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @param {FileSystemCallback<any>} callback callback
* @returns {void}
*/
class CacheBackend {
/**
* @param {number} duration max cache duration of items
* @param {function | undefined} provider async method
* @param {function | undefined} syncProvider sync method
* @param {BaseFileSystem} providerContext call context for the provider methods
*/
constructor(duration, provider, syncProvider, providerContext) {
this._duration = duration;
this._provider = provider;
this._syncProvider = syncProvider;
this._providerContext = providerContext;
/** @type {Map<string, FileSystemCallback<any>[]>} */
this._activeAsyncOperations = new Map();
/** @type {Map<string, { err: Error | null, result?: any, level: Set<string> }>} */
this._data = new Map();
/** @type {Set<string>[]} */
this._levels = [];
for (let i = 0; i < 10; i++) this._levels.push(new Set());
for (let i = 5000; i < duration; i += 500) this._levels.push(new Set());
this._currentLevel = 0;
this._tickInterval = Math.floor(duration / this._levels.length);
/** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC} */
this._mode = STORAGE_MODE_IDLE;
/** @type {NodeJS.Timeout | undefined} */
this._timeout = undefined;
/** @type {number | undefined} */
this._nextDecay = undefined;
// @ts-ignore
this.provide = provider ? this.provide.bind(this) : null;
// @ts-ignore
this.provideSync = syncProvider ? this.provideSync.bind(this) : null;
}
/**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @param {FileSystemCallback<any>} callback callback
* @returns {void}
*/
provide(path, options, callback) {
if (typeof options === "function") {
callback = options;
options = undefined;
}
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
callback(new TypeError("path must be a string, Buffer, URL or number"));
return;
}
const strPath = typeof path !== "string" ? path.toString() : path;
if (options) {
return /** @type {Function} */ (this._provider).call(
this._providerContext,
path,
options,
callback
);
}
// When in sync mode we can move to async mode
if (this._mode === STORAGE_MODE_SYNC) {
this._enterAsyncMode();
}
// Check in cache
let cacheEntry = this._data.get(strPath);
if (cacheEntry !== undefined) {
if (cacheEntry.err) return nextTick(callback, cacheEntry.err);
return nextTick(callback, null, cacheEntry.result);
}
// Check if there is already the same operation running
let callbacks = this._activeAsyncOperations.get(strPath);
if (callbacks !== undefined) {
callbacks.push(callback);
return;
}
this._activeAsyncOperations.set(strPath, (callbacks = [callback]));
// Run the operation
/** @type {Function} */
(this._provider).call(
this._providerContext,
path,
/**
* @param {Error | null} err error
* @param {any} [result] result
*/
(err, result) => {
this._activeAsyncOperations.delete(strPath);
this._storeResult(strPath, err, result);
// Enter async mode if not yet done
this._enterAsyncMode();
runCallbacks(
/** @type {FileSystemCallback<any>[]} */ (callbacks),
err,
result
);
}
);
}
/**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @returns {any} result
*/
provideSync(path, options) {
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
throw new TypeError("path must be a string");
}
const strPath = typeof path !== "string" ? path.toString() : path;
if (options) {
return /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path,
options
);
}
// In sync mode we may have to decay some cache items
if (this._mode === STORAGE_MODE_SYNC) {
this._runDecays();
}
// Check in cache
let cacheEntry = this._data.get(strPath);
if (cacheEntry !== undefined) {
if (cacheEntry.err) throw cacheEntry.err;
return cacheEntry.result;
}
// Get all active async operations
// This sync operation will also complete them
const callbacks = this._activeAsyncOperations.get(strPath);
this._activeAsyncOperations.delete(strPath);
// Run the operation
// When in idle mode, we will enter sync mode
let result;
try {
result = /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path
);
} catch (err) {
this._storeResult(strPath, /** @type {Error} */ (err), undefined);
this._enterSyncModeWhenIdle();
if (callbacks) {
runCallbacks(callbacks, /** @type {Error} */ (err), undefined);
}
throw err;
}
this._storeResult(strPath, null, result);
this._enterSyncModeWhenIdle();
if (callbacks) {
runCallbacks(callbacks, null, result);
}
return result;
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purge(what) {
if (!what) {
if (this._mode !== STORAGE_MODE_IDLE) {
this._data.clear();
for (const level of this._levels) {
level.clear();
}
this._enterIdleMode();
}
} else if (
typeof what === "string" ||
Buffer.isBuffer(what) ||
what instanceof URL ||
typeof what === "number"
) {
const strWhat = typeof what !== "string" ? what.toString() : what;
for (let [key, data] of this._data) {
if (key.startsWith(strWhat)) {
this._data.delete(key);
data.level.delete(key);
}
}
if (this._data.size === 0) {
this._enterIdleMode();
}
} else {
for (let [key, data] of this._data) {
for (const item of what) {
const strItem = typeof item !== "string" ? item.toString() : item;
if (key.startsWith(strItem)) {
this._data.delete(key);
data.level.delete(key);
break;
}
}
}
if (this._data.size === 0) {
this._enterIdleMode();
}
}
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purgeParent(what) {
if (!what) {
this.purge();
} else if (
typeof what === "string" ||
Buffer.isBuffer(what) ||
what instanceof URL ||
typeof what === "number"
) {
const strWhat = typeof what !== "string" ? what.toString() : what;
this.purge(dirname(strWhat));
} else {
const set = new Set();
for (const item of what) {
const strItem = typeof item !== "string" ? item.toString() : item;
set.add(dirname(strItem));
}
this.purge(set);
}
}
/**
* @param {string} path path
* @param {Error | null} err error
* @param {any} result result
*/
_storeResult(path, err, result) {
if (this._data.has(path)) return;
const level = this._levels[this._currentLevel];
this._data.set(path, { err, result, level });
level.add(path);
}
_decayLevel() {
const nextLevel = (this._currentLevel + 1) % this._levels.length;
const decay = this._levels[nextLevel];
this._currentLevel = nextLevel;
for (let item of decay) {
this._data.delete(item);
}
decay.clear();
if (this._data.size === 0) {
this._enterIdleMode();
} else {
/** @type {number} */
(this._nextDecay) += this._tickInterval;
}
}
_runDecays() {
while (
/** @type {number} */ (this._nextDecay) <= Date.now() &&
this._mode !== STORAGE_MODE_IDLE
) {
this._decayLevel();
}
}
_enterAsyncMode() {
let timeout = 0;
switch (this._mode) {
case STORAGE_MODE_ASYNC:
return;
case STORAGE_MODE_IDLE:
this._nextDecay = Date.now() + this._tickInterval;
timeout = this._tickInterval;
break;
case STORAGE_MODE_SYNC:
this._runDecays();
// _runDecays may change the mode
if (
/** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC}*/
(this._mode) === STORAGE_MODE_IDLE
)
return;
timeout = Math.max(
0,
/** @type {number} */ (this._nextDecay) - Date.now()
);
break;
}
this._mode = STORAGE_MODE_ASYNC;
const ref = setTimeout(() => {
this._mode = STORAGE_MODE_SYNC;
this._runDecays();
}, timeout);
if (ref.unref) ref.unref();
this._timeout = ref;
}
_enterSyncModeWhenIdle() {
if (this._mode === STORAGE_MODE_IDLE) {
this._mode = STORAGE_MODE_SYNC;
this._nextDecay = Date.now() + this._tickInterval;
}
}
_enterIdleMode() {
this._mode = STORAGE_MODE_IDLE;
this._nextDecay = undefined;
if (this._timeout) clearTimeout(this._timeout);
}
}
/**
* @template {function} Provider
* @template {function} AsyncProvider
* @template FileSystem
* @param {number} duration duration in ms files are cached
* @param {Provider | undefined} provider provider
* @param {AsyncProvider | undefined} syncProvider sync provider
* @param {BaseFileSystem} providerContext provider context
* @returns {OperationMergerBackend | CacheBackend} backend
*/
const createBackend = (duration, provider, syncProvider, providerContext) => {
if (duration > 0) {
return new CacheBackend(duration, provider, syncProvider, providerContext);
}
return new OperationMergerBackend(provider, syncProvider, providerContext);
};
module.exports = class CachedInputFileSystem {
/**
* @param {BaseFileSystem} fileSystem file system
* @param {number} duration duration in ms files are cached
*/
constructor(fileSystem, duration) {
this.fileSystem = fileSystem;
this._lstatBackend = createBackend(
duration,
this.fileSystem.lstat,
this.fileSystem.lstatSync,
this.fileSystem
);
const lstat = this._lstatBackend.provide;
this.lstat = /** @type {FileSystem["lstat"]} */ (lstat);
const lstatSync = this._lstatBackend.provideSync;
this.lstatSync = /** @type {SyncFileSystem["lstatSync"]} */ (lstatSync);
this._statBackend = createBackend(
duration,
this.fileSystem.stat,
this.fileSystem.statSync,
this.fileSystem
);
const stat = this._statBackend.provide;
this.stat = /** @type {FileSystem["stat"]} */ (stat);
const statSync = this._statBackend.provideSync;
this.statSync = /** @type {SyncFileSystem["statSync"]} */ (statSync);
this._readdirBackend = createBackend(
duration,
this.fileSystem.readdir,
this.fileSystem.readdirSync,
this.fileSystem
);
const readdir = this._readdirBackend.provide;
this.readdir = /** @type {FileSystem["readdir"]} */ (readdir);
const readdirSync = this._readdirBackend.provideSync;
this.readdirSync = /** @type {SyncFileSystem["readdirSync"]} */ (
readdirSync
);
this._readFileBackend = createBackend(
duration,
this.fileSystem.readFile,
this.fileSystem.readFileSync,
this.fileSystem
);
const readFile = this._readFileBackend.provide;
this.readFile = /** @type {FileSystem["readFile"]} */ (readFile);
const readFileSync = this._readFileBackend.provideSync;
this.readFileSync = /** @type {SyncFileSystem["readFileSync"]} */ (
readFileSync
);
this._readJsonBackend = createBackend(
duration,
// prettier-ignore
this.fileSystem.readJson ||
(this.readFile &&
(
/**
* @param {string} path path
* @param {FileSystemCallback<any>} callback
*/
(path, callback) => {
this.readFile(path, (err, buffer) => {
if (err) return callback(err);
if (!buffer || buffer.length === 0)
return callback(new Error("No file content"));
let data;
try {
data = JSON.parse(buffer.toString("utf-8"));
} catch (e) {
return callback(/** @type {Error} */ (e));
}
callback(null, data);
});
})
),
// prettier-ignore
this.fileSystem.readJsonSync ||
(this.readFileSync &&
(
/**
* @param {string} path path
* @returns {any} result
*/
(path) => {
const buffer = this.readFileSync(path);
const data = JSON.parse(buffer.toString("utf-8"));
return data;
}
)),
this.fileSystem
);
const readJson = this._readJsonBackend.provide;
this.readJson = /** @type {FileSystem["readJson"]} */ (readJson);
const readJsonSync = this._readJsonBackend.provideSync;
this.readJsonSync = /** @type {SyncFileSystem["readJsonSync"]} */ (
readJsonSync
);
this._readlinkBackend = createBackend(
duration,
this.fileSystem.readlink,
this.fileSystem.readlinkSync,
this.fileSystem
);
const readlink = this._readlinkBackend.provide;
this.readlink = /** @type {FileSystem["readlink"]} */ (readlink);
const readlinkSync = this._readlinkBackend.provideSync;
this.readlinkSync = /** @type {SyncFileSystem["readlinkSync"]} */ (
readlinkSync
);
this._realpathBackend = createBackend(
duration,
this.fileSystem.realpath,
this.fileSystem.realpathSync,
this.fileSystem
);
const realpath = this._realpathBackend.provide;
this.realpath = /** @type {FileSystem["realpath"]} */ (realpath);
const realpathSync = this._realpathBackend.provideSync;
this.realpathSync = /** @type {SyncFileSystem["realpathSync"]} */ (
realpathSync
);
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purge(what) {
this._statBackend.purge(what);
this._lstatBackend.purge(what);
this._readdirBackend.purgeParent(what);
this._readFileBackend.purge(what);
this._readlinkBackend.purge(what);
this._readJsonBackend.purge(what);
this._realpathBackend.purge(what);
}
};

View File

@ -0,0 +1,53 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const basename = require("./getPaths").basename;
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class CloneBasenamePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("CloneBasenamePlugin", (request, resolveContext, callback) => {
const requestPath = /** @type {string} */ (request.path);
const filename = /** @type {string} */ (basename(requestPath));
const filePath = resolver.join(requestPath, filename);
/** @type {ResolveRequest} */
const obj = {
...request,
path: filePath,
relativePath:
request.relativePath &&
resolver.join(request.relativePath, filename)
};
resolver.doResolve(
target,
obj,
"using path: " + filePath,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,59 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class ConditionalPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {Partial<ResolveRequest>} test compare object
* @param {string | null} message log message
* @param {boolean} allowAlternatives when false, do not continue with the current step when "test" matches
* @param {string | ResolveStepHook} target target
*/
constructor(source, test, message, allowAlternatives, target) {
this.source = source;
this.test = test;
this.message = message;
this.allowAlternatives = allowAlternatives;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
const { test, message, allowAlternatives } = this;
const keys = /** @type {(keyof ResolveRequest)[]} */ (Object.keys(test));
resolver
.getHook(this.source)
.tapAsync("ConditionalPlugin", (request, resolveContext, callback) => {
for (const prop of keys) {
if (request[prop] !== test[prop]) return callback();
}
resolver.doResolve(
target,
request,
message,
resolveContext,
allowAlternatives
? callback
: (err, result) => {
if (err) return callback(err);
// Don't allow other alternatives
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
});
}
};

View File

@ -0,0 +1,98 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class DescriptionFilePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string[]} filenames filenames
* @param {boolean} pathIsFile pathIsFile
* @param {string | ResolveStepHook} target target
*/
constructor(source, filenames, pathIsFile, target) {
this.source = source;
this.filenames = filenames;
this.pathIsFile = pathIsFile;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync(
"DescriptionFilePlugin",
(request, resolveContext, callback) => {
const path = request.path;
if (!path) return callback();
const directory = this.pathIsFile
? DescriptionFileUtils.cdUp(path)
: path;
if (!directory) return callback();
DescriptionFileUtils.loadDescriptionFile(
resolver,
directory,
this.filenames,
request.descriptionFilePath
? {
path: request.descriptionFilePath,
content: request.descriptionFileData,
directory: /** @type {string} */ (request.descriptionFileRoot)
}
: undefined,
resolveContext,
(err, result) => {
if (err) return callback(err);
if (!result) {
if (resolveContext.log)
resolveContext.log(
`No description file found in ${directory} or above`
);
return callback();
}
const relativePath =
"." + path.slice(result.directory.length).replace(/\\/g, "/");
/** @type {ResolveRequest} */
const obj = {
...request,
descriptionFilePath: result.path,
descriptionFileData: result.content,
descriptionFileRoot: result.directory,
relativePath: relativePath
};
resolver.doResolve(
target,
obj,
"using description file: " +
result.path +
" (relative path: " +
relativePath +
")",
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow other processing
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
}
);
}
);
}
};

View File

@ -0,0 +1,201 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonObject} JsonObject */
/** @typedef {import("./Resolver").JsonValue} JsonValue */
/** @typedef {import("./Resolver").ResolveContext} ResolveContext */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/**
* @typedef {Object} DescriptionFileInfo
* @property {JsonObject=} content
* @property {string} path
* @property {string} directory
*/
/**
* @callback ErrorFirstCallback
* @param {Error|null=} error
* @param {DescriptionFileInfo=} result
*/
/**
* @typedef {Object} Result
* @property {string} path path to description file
* @property {string} directory directory of description file
* @property {JsonObject} content content of description file
*/
/**
* @param {Resolver} resolver resolver
* @param {string} directory directory
* @param {string[]} filenames filenames
* @param {DescriptionFileInfo|undefined} oldInfo oldInfo
* @param {ResolveContext} resolveContext resolveContext
* @param {ErrorFirstCallback} callback callback
*/
function loadDescriptionFile(
resolver,
directory,
filenames,
oldInfo,
resolveContext,
callback
) {
(function findDescriptionFile() {
if (oldInfo && oldInfo.directory === directory) {
// We already have info for this directory and can reuse it
return callback(null, oldInfo);
}
forEachBail(
filenames,
/**
* @param {string} filename filename
* @param {(err?: null|Error, result?: null|Result) => void} callback callback
* @returns {void}
*/
(filename, callback) => {
const descriptionFilePath = resolver.join(directory, filename);
if (resolver.fileSystem.readJson) {
resolver.fileSystem.readJson(descriptionFilePath, (err, content) => {
if (err) {
if (
typeof (/** @type {NodeJS.ErrnoException} */ (err).code) !==
"undefined"
) {
if (resolveContext.missingDependencies) {
resolveContext.missingDependencies.add(descriptionFilePath);
}
return callback();
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
return onJson(err);
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
onJson(null, content);
});
} else {
resolver.fileSystem.readFile(descriptionFilePath, (err, content) => {
if (err) {
if (resolveContext.missingDependencies) {
resolveContext.missingDependencies.add(descriptionFilePath);
}
return callback();
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
/** @type {JsonObject | undefined} */
let json;
if (content) {
try {
json = JSON.parse(content.toString());
} catch (/** @type {unknown} */ e) {
return onJson(/** @type {Error} */ (e));
}
} else {
return onJson(new Error("No content in file"));
}
onJson(null, json);
});
}
/**
* @param {null|Error} [err] error
* @param {JsonObject} [content] content
* @returns {void}
*/
function onJson(err, content) {
if (err) {
if (resolveContext.log)
resolveContext.log(
descriptionFilePath + " (directory description file): " + err
);
else
err.message =
descriptionFilePath + " (directory description file): " + err;
return callback(err);
}
callback(null, {
content: /** @type {JsonObject} */ (content),
directory,
path: descriptionFilePath
});
}
},
/**
* @param {null|Error} [err] error
* @param {null|Result} [result] result
* @returns {void}
*/
(err, result) => {
if (err) return callback(err);
if (result) {
return callback(null, result);
} else {
const dir = cdUp(directory);
if (!dir) {
return callback();
} else {
directory = dir;
return findDescriptionFile();
}
}
}
);
})();
}
/**
* @param {JsonObject} content content
* @param {string|string[]} field field
* @returns {JsonValue | undefined} field data
*/
function getField(content, field) {
if (!content) return undefined;
if (Array.isArray(field)) {
/** @type {JsonValue} */
let current = content;
for (let j = 0; j < field.length; j++) {
if (current === null || typeof current !== "object") {
current = null;
break;
}
current = /** @type {JsonObject} */ (current)[field[j]];
}
return current;
} else {
return content[field];
}
}
/**
* @param {string} directory directory
* @returns {string|null} parent directory or null
*/
function cdUp(directory) {
if (directory === "/") return null;
const i = directory.lastIndexOf("/"),
j = directory.lastIndexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if (p < 0) return null;
return directory.slice(0, p || 1);
}
exports.loadDescriptionFile = loadDescriptionFile;
exports.getField = getField;
exports.cdUp = cdUp;

View File

@ -0,0 +1,63 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class DirectoryExistsPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync(
"DirectoryExistsPlugin",
(request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const directory = request.path;
if (!directory) return callback();
fs.stat(directory, (err, stat) => {
if (err || !stat) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(directory);
if (resolveContext.log)
resolveContext.log(directory + " doesn't exist");
return callback();
}
if (!stat.isDirectory()) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(directory);
if (resolveContext.log)
resolveContext.log(directory + " is not a directory");
return callback();
}
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(directory);
resolver.doResolve(
target,
request,
`existing directory ${directory}`,
resolveContext,
callback
);
});
}
);
}
};

View File

@ -0,0 +1,200 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
const forEachBail = require("./forEachBail");
const { processExportsField } = require("./util/entrypoints");
const { parseIdentifier } = require("./util/identifier");
const {
invalidSegmentRegEx,
deprecatedInvalidSegmentRegEx
} = require("./util/path");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonObject} JsonObject */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {import("./util/entrypoints").ExportsField} ExportsField */
/** @typedef {import("./util/entrypoints").FieldProcessor} FieldProcessor */
module.exports = class ExportsFieldPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {Set<string>} conditionNames condition names
* @param {string | string[]} fieldNamePath name path
* @param {string | ResolveStepHook} target target
*/
constructor(source, conditionNames, fieldNamePath, target) {
this.source = source;
this.target = target;
this.conditionNames = conditionNames;
this.fieldName = fieldNamePath;
/** @type {WeakMap<JsonObject, FieldProcessor>} */
this.fieldProcessorCache = new WeakMap();
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("ExportsFieldPlugin", (request, resolveContext, callback) => {
// When there is no description file, abort
if (!request.descriptionFilePath) return callback();
if (
// When the description file is inherited from parent, abort
// (There is no description file inside of this package)
request.relativePath !== "." ||
request.request === undefined
)
return callback();
const remainingRequest =
request.query || request.fragment
? (request.request === "." ? "./" : request.request) +
request.query +
request.fragment
: request.request;
const exportsField =
/** @type {ExportsField|null|undefined} */
(
DescriptionFileUtils.getField(
/** @type {JsonObject} */ (request.descriptionFileData),
this.fieldName
)
);
if (!exportsField) return callback();
if (request.directory) {
return callback(
new Error(
`Resolving to directories is not possible with the exports field (request was ${remainingRequest}/)`
)
);
}
/** @type {string[]} */
let paths;
/** @type {string | null} */
let usedField;
try {
// We attach the cache to the description file instead of the exportsField value
// because we use a WeakMap and the exportsField could be a string too.
// Description file is always an object when exports field can be accessed.
let fieldProcessor = this.fieldProcessorCache.get(
/** @type {JsonObject} */ (request.descriptionFileData)
);
if (fieldProcessor === undefined) {
fieldProcessor = processExportsField(exportsField);
this.fieldProcessorCache.set(
/** @type {JsonObject} */ (request.descriptionFileData),
fieldProcessor
);
}
[paths, usedField] = fieldProcessor(
remainingRequest,
this.conditionNames
);
} catch (/** @type {unknown} */ err) {
if (resolveContext.log) {
resolveContext.log(
`Exports field in ${request.descriptionFilePath} can't be processed: ${err}`
);
}
return callback(/** @type {Error} */ (err));
}
if (paths.length === 0) {
return callback(
new Error(
`Package path ${remainingRequest} is not exported from package ${request.descriptionFileRoot} (see exports field in ${request.descriptionFilePath})`
)
);
}
forEachBail(
paths,
/**
* @param {string} p path
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @param {number} i index
* @returns {void}
*/
(p, callback, i) => {
const parsedIdentifier = parseIdentifier(p);
if (!parsedIdentifier) return callback();
const [relativePath, query, fragment] = parsedIdentifier;
if (relativePath.length === 0 || !relativePath.startsWith("./")) {
if (paths.length === i) {
return callback(
new Error(
`Invalid "exports" target "${p}" defined for "${usedField}" in the package config ${request.descriptionFilePath}, targets must start with "./"`
)
);
}
return callback();
}
if (
invalidSegmentRegEx.exec(relativePath.slice(2)) !== null &&
deprecatedInvalidSegmentRegEx.test(relativePath.slice(2)) !== null
) {
if (paths.length === i) {
return callback(
new Error(
`Invalid "exports" target "${p}" defined for "${usedField}" in the package config ${request.descriptionFilePath}, targets must start with "./"`
)
);
}
return callback();
}
/** @type {ResolveRequest} */
const obj = {
...request,
request: undefined,
path: resolver.join(
/** @type {string} */ (request.descriptionFileRoot),
relativePath
),
relativePath,
query,
fragment
};
resolver.doResolve(
target,
obj,
"using exports field: " + p,
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow to continue - https://github.com/webpack/enhanced-resolve/issues/400
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
},
/**
* @param {null|Error} [err] error
* @param {null|ResolveRequest} [result] result
* @returns {void}
*/
(err, result) => callback(err, result || null)
);
});
}
};

View File

@ -0,0 +1,101 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const forEachBail = require("./forEachBail");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {{ alias: string|string[], extension: string }} ExtensionAliasOption */
module.exports = class ExtensionAliasPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {ExtensionAliasOption} options options
* @param {string | ResolveStepHook} target target
*/
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
const { extension, alias } = this.options;
resolver
.getHook(this.source)
.tapAsync("ExtensionAliasPlugin", (request, resolveContext, callback) => {
const requestPath = request.request;
if (!requestPath || !requestPath.endsWith(extension)) return callback();
const isAliasString = typeof alias === "string";
/**
* @param {string} alias extension alias
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @param {number} [index] index
* @returns {void}
*/
const resolve = (alias, callback, index) => {
const newRequest = `${requestPath.slice(
0,
-extension.length
)}${alias}`;
return resolver.doResolve(
target,
{
...request,
request: newRequest,
fullySpecified: true
},
`aliased from extension alias with mapping '${extension}' to '${alias}'`,
resolveContext,
(err, result) => {
// Throw error if we are on the last alias (for multiple aliases) and it failed, always throw if we are not an array or we have only one alias
if (!isAliasString && index) {
if (index !== this.options.alias.length) {
if (resolveContext.log) {
resolveContext.log(
`Failed to alias from extension alias with mapping '${extension}' to '${alias}' for '${newRequest}': ${err}`
);
}
return callback(null, result);
}
return callback(err, result);
} else {
callback(err, result);
}
}
);
};
/**
* @param {null|Error} [err] error
* @param {null|ResolveRequest} [result] result
* @returns {void}
*/
const stoppingCallback = (err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
// Don't allow other aliasing or raw request
return callback(null, null);
};
if (isAliasString) {
resolve(alias, stoppingCallback);
} else if (alias.length > 1) {
forEachBail(alias, resolve, stoppingCallback);
} else {
resolve(alias[0], stoppingCallback);
}
});
}
};

View File

@ -0,0 +1,58 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class FileExistsPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
const fs = resolver.fileSystem;
resolver
.getHook(this.source)
.tapAsync("FileExistsPlugin", (request, resolveContext, callback) => {
const file = request.path;
if (!file) return callback();
fs.stat(file, (err, stat) => {
if (err || !stat) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(file);
if (resolveContext.log) resolveContext.log(file + " doesn't exist");
return callback();
}
if (!stat.isFile()) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(file);
if (resolveContext.log) resolveContext.log(file + " is not a file");
return callback();
}
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(file);
resolver.doResolve(
target,
request,
"existing file: " + file,
resolveContext,
callback
);
});
});
}
};

View File

@ -0,0 +1,223 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
const forEachBail = require("./forEachBail");
const { processImportsField } = require("./util/entrypoints");
const { parseIdentifier } = require("./util/identifier");
const {
invalidSegmentRegEx,
deprecatedInvalidSegmentRegEx
} = require("./util/path");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonObject} JsonObject */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {import("./util/entrypoints").FieldProcessor} FieldProcessor */
/** @typedef {import("./util/entrypoints").ImportsField} ImportsField */
const dotCode = ".".charCodeAt(0);
module.exports = class ImportsFieldPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {Set<string>} conditionNames condition names
* @param {string | string[]} fieldNamePath name path
* @param {string | ResolveStepHook} targetFile target file
* @param {string | ResolveStepHook} targetPackage target package
*/
constructor(
source,
conditionNames,
fieldNamePath,
targetFile,
targetPackage
) {
this.source = source;
this.targetFile = targetFile;
this.targetPackage = targetPackage;
this.conditionNames = conditionNames;
this.fieldName = fieldNamePath;
/** @type {WeakMap<JsonObject, FieldProcessor>} */
this.fieldProcessorCache = new WeakMap();
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const targetFile = resolver.ensureHook(this.targetFile);
const targetPackage = resolver.ensureHook(this.targetPackage);
resolver
.getHook(this.source)
.tapAsync("ImportsFieldPlugin", (request, resolveContext, callback) => {
// When there is no description file, abort
if (!request.descriptionFilePath || request.request === undefined) {
return callback();
}
const remainingRequest =
request.request + request.query + request.fragment;
const importsField =
/** @type {ImportsField|null|undefined} */
(
DescriptionFileUtils.getField(
/** @type {JsonObject} */ (request.descriptionFileData),
this.fieldName
)
);
if (!importsField) return callback();
if (request.directory) {
return callback(
new Error(
`Resolving to directories is not possible with the imports field (request was ${remainingRequest}/)`
)
);
}
/** @type {string[]} */
let paths;
/** @type {string | null} */
let usedField;
try {
// We attach the cache to the description file instead of the importsField value
// because we use a WeakMap and the importsField could be a string too.
// Description file is always an object when exports field can be accessed.
let fieldProcessor = this.fieldProcessorCache.get(
/** @type {JsonObject} */ (request.descriptionFileData)
);
if (fieldProcessor === undefined) {
fieldProcessor = processImportsField(importsField);
this.fieldProcessorCache.set(
/** @type {JsonObject} */ (request.descriptionFileData),
fieldProcessor
);
}
[paths, usedField] = fieldProcessor(
remainingRequest,
this.conditionNames
);
} catch (/** @type {unknown} */ err) {
if (resolveContext.log) {
resolveContext.log(
`Imports field in ${request.descriptionFilePath} can't be processed: ${err}`
);
}
return callback(/** @type {Error} */ (err));
}
if (paths.length === 0) {
return callback(
new Error(
`Package import ${remainingRequest} is not imported from package ${request.descriptionFileRoot} (see imports field in ${request.descriptionFilePath})`
)
);
}
forEachBail(
paths,
/**
* @param {string} p path
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @param {number} i index
* @returns {void}
*/
(p, callback, i) => {
const parsedIdentifier = parseIdentifier(p);
if (!parsedIdentifier) return callback();
const [path_, query, fragment] = parsedIdentifier;
switch (path_.charCodeAt(0)) {
// should be relative
case dotCode: {
if (
invalidSegmentRegEx.exec(path_.slice(2)) !== null &&
deprecatedInvalidSegmentRegEx.test(path_.slice(2)) !== null
) {
if (paths.length === i) {
return callback(
new Error(
`Invalid "imports" target "${p}" defined for "${usedField}" in the package config ${request.descriptionFilePath}, targets must start with "./"`
)
);
}
return callback();
}
/** @type {ResolveRequest} */
const obj = {
...request,
request: undefined,
path: resolver.join(
/** @type {string} */ (request.descriptionFileRoot),
path_
),
relativePath: path_,
query,
fragment
};
resolver.doResolve(
targetFile,
obj,
"using imports field: " + p,
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow to continue - https://github.com/webpack/enhanced-resolve/issues/400
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
break;
}
// package resolving
default: {
/** @type {ResolveRequest} */
const obj = {
...request,
request: path_,
relativePath: path_,
fullySpecified: true,
query,
fragment
};
resolver.doResolve(
targetPackage,
obj,
"using imports field: " + p,
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow to continue - https://github.com/webpack/enhanced-resolve/issues/400
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
}
}
},
/**
* @param {null|Error} [err] error
* @param {null|ResolveRequest} [result] result
* @returns {void}
*/
(err, result) => callback(err, result || null)
);
});
}
};

View File

@ -0,0 +1,75 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
const namespaceStartCharCode = "@".charCodeAt(0);
module.exports = class JoinRequestPartPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync(
"JoinRequestPartPlugin",
(request, resolveContext, callback) => {
const req = request.request || "";
let i = req.indexOf("/", 3);
if (i >= 0 && req.charCodeAt(2) === namespaceStartCharCode) {
i = req.indexOf("/", i + 1);
}
/** @type {string} */
let moduleName;
/** @type {string} */
let remainingRequest;
/** @type {boolean} */
let fullySpecified;
if (i < 0) {
moduleName = req;
remainingRequest = ".";
fullySpecified = false;
} else {
moduleName = req.slice(0, i);
remainingRequest = "." + req.slice(i);
fullySpecified = /** @type {boolean} */ (request.fullySpecified);
}
/** @type {ResolveRequest} */
const obj = {
...request,
path: resolver.join(
/** @type {string} */
(request.path),
moduleName
),
relativePath:
request.relativePath &&
resolver.join(request.relativePath, moduleName),
request: remainingRequest,
fullySpecified
};
resolver.doResolve(target, obj, null, resolveContext, callback);
}
);
}
};

View File

@ -0,0 +1,45 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class JoinRequestPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("JoinRequestPlugin", (request, resolveContext, callback) => {
const requestPath = /** @type {string} */ (request.path);
const requestRequest = /** @type {string} */ (request.request);
/** @type {ResolveRequest} */
const obj = {
...request,
path: resolver.join(requestPath, requestRequest),
relativePath:
request.relativePath &&
resolver.join(request.relativePath, requestRequest),
request: undefined
};
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};

View File

@ -0,0 +1,54 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class LogInfoPlugin {
/**
* @param {string | ResolveStepHook} source source
*/
constructor(source) {
this.source = source;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const source = this.source;
resolver
.getHook(this.source)
.tapAsync("LogInfoPlugin", (request, resolveContext, callback) => {
if (!resolveContext.log) return callback();
const log = resolveContext.log;
const prefix = "[" + source + "] ";
if (request.path)
log(prefix + "Resolving in directory: " + request.path);
if (request.request)
log(prefix + "Resolving request: " + request.request);
if (request.module) log(prefix + "Request is an module request.");
if (request.directory) log(prefix + "Request is a directory request.");
if (request.query)
log(prefix + "Resolving request query: " + request.query);
if (request.fragment)
log(prefix + "Resolving request fragment: " + request.fragment);
if (request.descriptionFilePath)
log(
prefix + "Has description data from " + request.descriptionFilePath
);
if (request.relativePath)
log(
prefix +
"Relative path from description file is: " +
request.relativePath
);
callback();
});
}
};

View File

@ -0,0 +1,90 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
const DescriptionFileUtils = require("./DescriptionFileUtils");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonObject} JsonObject */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {{name: string|Array<string>, forceRelative: boolean}} MainFieldOptions */
const alreadyTriedMainField = Symbol("alreadyTriedMainField");
module.exports = class MainFieldPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {MainFieldOptions} options options
* @param {string | ResolveStepHook} target target
*/
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("MainFieldPlugin", (request, resolveContext, callback) => {
if (
request.path !== request.descriptionFileRoot ||
/** @type {ResolveRequest & { [alreadyTriedMainField]?: string }} */
(request)[alreadyTriedMainField] === request.descriptionFilePath ||
!request.descriptionFilePath
)
return callback();
const filename = path.basename(request.descriptionFilePath);
let mainModule =
/** @type {string|null|undefined} */
(
DescriptionFileUtils.getField(
/** @type {JsonObject} */ (request.descriptionFileData),
this.options.name
)
);
if (
!mainModule ||
typeof mainModule !== "string" ||
mainModule === "." ||
mainModule === "./"
) {
return callback();
}
if (this.options.forceRelative && !/^\.\.?\//.test(mainModule))
mainModule = "./" + mainModule;
/** @type {ResolveRequest & { [alreadyTriedMainField]?: string }} */
const obj = {
...request,
request: mainModule,
module: false,
directory: mainModule.endsWith("/"),
[alreadyTriedMainField]: request.descriptionFilePath
};
return resolver.doResolve(
target,
obj,
"use " +
mainModule +
" from " +
this.options.name +
" in " +
filename,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,9 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
// TODO remove in next major
module.exports = require("./ModulesInHierarchicalDirectoriesPlugin");

View File

@ -0,0 +1,87 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
const getPaths = require("./getPaths");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class ModulesInHierarchicalDirectoriesPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | Array<string>} directories directories
* @param {string | ResolveStepHook} target target
*/
constructor(source, directories, target) {
this.source = source;
this.directories = /** @type {Array<string>} */ ([]).concat(directories);
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync(
"ModulesInHierarchicalDirectoriesPlugin",
(request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const addrs = getPaths(/** @type {string} */ (request.path))
.paths.map(p => {
return this.directories.map(d => resolver.join(p, d));
})
.reduce((array, p) => {
array.push.apply(array, p);
return array;
}, []);
forEachBail(
addrs,
/**
* @param {string} addr addr
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @returns {void}
*/
(addr, callback) => {
fs.stat(addr, (err, stat) => {
if (!err && stat && stat.isDirectory()) {
/** @type {ResolveRequest} */
const obj = {
...request,
path: addr,
request: "./" + request.request,
module: false
};
const message = "looking for modules in " + addr;
return resolver.doResolve(
target,
obj,
message,
resolveContext,
callback
);
}
if (resolveContext.log)
resolveContext.log(
addr + " doesn't exist or is not a directory"
);
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(addr);
return callback();
});
},
callback
);
}
);
}
};

View File

@ -0,0 +1,49 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class ModulesInRootPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string} path path
* @param {string | ResolveStepHook} target target
*/
constructor(source, path, target) {
this.source = source;
this.path = path;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("ModulesInRootPlugin", (request, resolveContext, callback) => {
/** @type {ResolveRequest} */
const obj = {
...request,
path: this.path,
request: "./" + request.request,
module: false
};
resolver.doResolve(
target,
obj,
"looking for modules in " + this.path,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class NextPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("NextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
};

View File

@ -0,0 +1,76 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class ParsePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {Partial<ResolveRequest>} requestOptions request options
* @param {string | ResolveStepHook} target target
*/
constructor(source, requestOptions, target) {
this.source = source;
this.requestOptions = requestOptions;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("ParsePlugin", (request, resolveContext, callback) => {
const parsed = resolver.parse(/** @type {string} */ (request.request));
/** @type {ResolveRequest} */
const obj = { ...request, ...parsed, ...this.requestOptions };
if (request.query && !parsed.query) {
obj.query = request.query;
}
if (request.fragment && !parsed.fragment) {
obj.fragment = request.fragment;
}
if (parsed && resolveContext.log) {
if (parsed.module) resolveContext.log("Parsed request is a module");
if (parsed.directory)
resolveContext.log("Parsed request is a directory");
}
// There is an edge-case where a request with # can be a path or a fragment -> try both
if (obj.request && !obj.query && obj.fragment) {
const directory = obj.fragment.endsWith("/");
/** @type {ResolveRequest} */
const alternative = {
...obj,
directory,
request:
obj.request +
(obj.directory ? "/" : "") +
(directory ? obj.fragment.slice(0, -1) : obj.fragment),
fragment: ""
};
resolver.doResolve(
target,
alternative,
null,
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
resolver.doResolve(target, obj, null, resolveContext, callback);
}
);
return;
}
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};

133
app_vue/node_modules/enhanced-resolve/lib/PnpPlugin.js generated vendored Normal file
View File

@ -0,0 +1,133 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Maël Nison @arcanis
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/**
* @typedef {Object} PnpApiImpl
* @property {function(string, string, object): string | null} resolveToUnqualified
*/
module.exports = class PnpPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {PnpApiImpl} pnpApi pnpApi
* @param {string | ResolveStepHook} target target
* @param {string | ResolveStepHook} alternateTarget alternateTarget
*/
constructor(source, pnpApi, target, alternateTarget) {
this.source = source;
this.pnpApi = pnpApi;
this.target = target;
this.alternateTarget = alternateTarget;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
/** @type {ResolveStepHook} */
const target = resolver.ensureHook(this.target);
const alternateTarget = resolver.ensureHook(this.alternateTarget);
resolver
.getHook(this.source)
.tapAsync("PnpPlugin", (request, resolveContext, callback) => {
const req = request.request;
if (!req) return callback();
// The trailing slash indicates to PnP that this value is a folder rather than a file
const issuer = `${request.path}/`;
const packageMatch = /^(@[^/]+\/)?[^/]+/.exec(req);
if (!packageMatch) return callback();
const packageName = packageMatch[0];
const innerRequest = `.${req.slice(packageName.length)}`;
/** @type {string|undefined|null} */
let resolution;
/** @type {string|undefined|null} */
let apiResolution;
try {
resolution = this.pnpApi.resolveToUnqualified(packageName, issuer, {
considerBuiltins: false
});
if (resolution === null) {
// This is either not a PnP managed issuer or it's a Node builtin
// Try to continue resolving with our alternatives
resolver.doResolve(
alternateTarget,
request,
"issuer is not managed by a pnpapi",
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
// Skip alternatives
return callback(null, null);
}
);
return;
}
if (resolveContext.fileDependencies) {
apiResolution = this.pnpApi.resolveToUnqualified("pnpapi", issuer, {
considerBuiltins: false
});
}
} catch (/** @type {unknown} */ error) {
if (
/** @type {Error & { code: string }} */
(error).code === "MODULE_NOT_FOUND" &&
/** @type {Error & { pnpCode: string }} */
(error).pnpCode === "UNDECLARED_DEPENDENCY"
) {
// This is not a PnP managed dependency.
// Try to continue resolving with our alternatives
if (resolveContext.log) {
resolveContext.log(`request is not managed by the pnpapi`);
for (const line of /** @type {Error} */ (error).message
.split("\n")
.filter(Boolean))
resolveContext.log(` ${line}`);
}
return callback();
}
return callback(/** @type {Error} */ (error));
}
if (resolution === packageName) return callback();
if (apiResolution && resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(apiResolution);
}
/** @type {ResolveRequest} */
const obj = {
...request,
path: resolution,
request: innerRequest,
ignoreSymlinks: true,
fullySpecified: request.fullySpecified && innerRequest !== "."
};
resolver.doResolve(
target,
obj,
`resolved by pnp to ${resolution}`,
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
// Skip alternatives
return callback(null, null);
}
);
});
}
};

800
app_vue/node_modules/enhanced-resolve/lib/Resolver.js generated vendored Normal file
View File

@ -0,0 +1,800 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { AsyncSeriesBailHook, AsyncSeriesHook, SyncHook } = require("tapable");
const createInnerContext = require("./createInnerContext");
const { parseIdentifier } = require("./util/identifier");
const {
normalize,
cachedJoin: join,
getType,
PathType
} = require("./util/path");
/** @typedef {import("./ResolverFactory").ResolveOptions} ResolveOptions */
/** @typedef {Error & { details?: string }} ErrorWithDetail */
/** @typedef {(err: ErrorWithDetail | null, res?: string | false, req?: ResolveRequest) => void} ResolveCallback */
/**
* @typedef {Object} PossibleFileSystemError
* @property {string=} code
* @property {number=} errno
* @property {string=} path
* @property {string=} syscall
*/
/**
* @template T
* @callback FileSystemCallback
* @param {PossibleFileSystemError & Error | null} err
* @param {T=} result
*/
/**
* @typedef {string | Buffer | URL} PathLike
*/
/**
* @typedef {PathLike | number} PathOrFileDescriptor
*/
/**
* @typedef {Object} ObjectEncodingOptions
* @property {BufferEncoding | null | undefined} [encoding]
*/
/** @typedef {function(NodeJS.ErrnoException | null, string=): void} StringCallback */
/** @typedef {function(NodeJS.ErrnoException | null, Buffer=): void} BufferCallback */
/** @typedef {function(NodeJS.ErrnoException | null, (string | Buffer)=): void} StringOrBufferCallback */
/** @typedef {function(NodeJS.ErrnoException | null, IStats=): void} StatsCallback */
/** @typedef {function(NodeJS.ErrnoException | null, IBigIntStats=): void} BigIntStatsCallback */
/** @typedef {function(NodeJS.ErrnoException | null, (IStats | IBigIntStats)=): void} StatsOrBigIntStatsCallback */
/** @typedef {function(NodeJS.ErrnoException | Error | null, JsonObject=): void} ReadJsonCallback */
/** @typedef {function(NodeJS.ErrnoException | null, string[]=): void} ReaddirStringCallback */
/** @typedef {function(NodeJS.ErrnoException | null, Buffer[]=): void} ReaddirBufferCallback */
/** @typedef {function(NodeJS.ErrnoException | null, (string[] | Buffer[])=): void} ReaddirStringOrBufferCallback */
/** @typedef {function(NodeJS.ErrnoException | null, Dirent[]=): void} ReaddirDirentCallback */
/**
* @template T
* @typedef {Object} IStatsBase
* @property {() => boolean} isFile
* @property {() => boolean} isDirectory
* @property {() => boolean} isBlockDevice
* @property {() => boolean} isCharacterDevice
* @property {() => boolean} isSymbolicLink
* @property {() => boolean} isFIFO
* @property {() => boolean} isSocket
* @property {T} dev
* @property {T} ino
* @property {T} mode
* @property {T} nlink
* @property {T} uid
* @property {T} gid
* @property {T} rdev
* @property {T} size
* @property {T} blksize
* @property {T} blocks
* @property {T} atimeMs
* @property {T} mtimeMs
* @property {T} ctimeMs
* @property {T} birthtimeMs
* @property {Date} atime
* @property {Date} mtime
* @property {Date} ctime
* @property {Date} birthtime
*/
/**
* @typedef {IStatsBase<number>} IStats
*/
/**
* @typedef {IStatsBase<bigint> & { atimeNs: bigint, mtimeNs: bigint, ctimeNs: bigint, birthtimeNs: bigint }} IBigIntStats
*/
/**
* @typedef {Object} Dirent
* @property {() => boolean} isFile
* @property {() => boolean} isDirectory
* @property {() => boolean} isBlockDevice
* @property {() => boolean} isCharacterDevice
* @property {() => boolean} isSymbolicLink
* @property {() => boolean} isFIFO
* @property {() => boolean} isSocket
* @property {string} name
* @property {string} path
*/
/**
* @typedef {Object} StatOptions
* @property {(boolean | undefined)=} bigint
*/
/**
* @typedef {Object} StatSyncOptions
* @property {(boolean | undefined)=} bigint
* @property {(boolean | undefined)=} throwIfNoEntry
*/
/**
* @typedef {{
* (path: PathOrFileDescriptor, options: ({ encoding?: null | undefined, flag?: string | undefined } & import("events").Abortable) | undefined | null, callback: BufferCallback): void;
* (path: PathOrFileDescriptor, options: ({ encoding: BufferEncoding, flag?: string | undefined } & import("events").Abortable) | BufferEncoding, callback: StringCallback): void;
* (path: PathOrFileDescriptor, options: (ObjectEncodingOptions & { flag?: string | undefined } & import("events").Abortable) | BufferEncoding | undefined | null, callback: StringOrBufferCallback): void;
* (path: PathOrFileDescriptor, callback: BufferCallback): void;
* }} ReadFile
*/
/**
* @typedef {ObjectEncodingOptions | BufferEncoding | undefined | null} EncodingOption
*/
/**
* @typedef {'buffer'| { encoding: 'buffer' }} BufferEncodingOption
*/
/**
* @typedef {{
* (path: PathOrFileDescriptor, options?: { encoding?: null | undefined, flag?: string | undefined } | null): Buffer;
* (path: PathOrFileDescriptor, options: { encoding: BufferEncoding, flag?: string | undefined } | BufferEncoding): string;
* (path: PathOrFileDescriptor, options?: (ObjectEncodingOptions & { flag?: string | undefined }) | BufferEncoding | null): string | Buffer;
* }} ReadFileSync
*/
/**
* @typedef {{
* (path: PathLike, options: { encoding: BufferEncoding | null, withFileTypes?: false | undefined, recursive?: boolean | undefined } | BufferEncoding | undefined | null, callback: ReaddirStringCallback): void;
* (path: PathLike, options: { encoding: 'buffer', withFileTypes?: false | undefined, recursive?: boolean | undefined } | 'buffer', callback: ReaddirBufferCallback): void;
* (path: PathLike, callback: ReaddirStringCallback): void;
* (path: PathLike, options: (ObjectEncodingOptions & { withFileTypes?: false | undefined, recursive?: boolean | undefined }) | BufferEncoding | undefined | null, callback: ReaddirStringOrBufferCallback): void;
* (path: PathLike, options: ObjectEncodingOptions & { withFileTypes: true, recursive?: boolean | undefined }, callback: ReaddirDirentCallback): void;
* }} Readdir
*/
/**
* @typedef {{
* (path: PathLike, options?: { encoding: BufferEncoding | null, withFileTypes?: false | undefined, recursive?: boolean | undefined } | BufferEncoding | null): string[];
* (path: PathLike, options: { encoding: 'buffer', withFileTypes?: false | undefined, recursive?: boolean | undefined } | 'buffer'): Buffer[];
* (path: PathLike, options?: (ObjectEncodingOptions & { withFileTypes?: false | undefined, recursive?: boolean | undefined }) | BufferEncoding | null): string[] | Buffer[];
* (path: PathLike, options: ObjectEncodingOptions & { withFileTypes: true, recursive?: boolean | undefined }): Dirent[];
* }} ReaddirSync
/**
* @typedef {function(PathOrFileDescriptor, ReadJsonCallback): void} ReadJson
*/
/**
* @typedef {function(PathOrFileDescriptor): JsonObject} ReadJsonSync
*/
/**
* @typedef {{
* (path: PathLike, options: EncodingOption, callback: StringCallback): void;
* (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void;
* (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void;
* (path: PathLike, callback: StringCallback): void;
* }} Readlink
*/
/**
* @typedef {{
* (path: PathLike, options?: EncodingOption): string;
* (path: PathLike, options: BufferEncodingOption): Buffer;
* (path: PathLike, options?: EncodingOption): string | Buffer;
* }} ReadlinkSync
*/
/**
* @typedef {{
* (path: PathLike, callback: StatsCallback): void;
* (path: PathLike, options: (StatOptions & { bigint?: false | undefined }) | undefined, callback: StatsCallback): void;
* (path: PathLike, options: StatOptions & { bigint: true }, callback: BigIntStatsCallback): void;
* (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void;
* }} LStat
*/
/**
* @typedef {{
* (path: PathLike, options?: undefined): IStats;
* (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry: false }): IStats | undefined;
* (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry: false }): IBigIntStats | undefined;
* (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined }): IStats;
* (path: PathLike, options: StatSyncOptions & { bigint: true }): IBigIntStats;
* (path: PathLike, options: StatSyncOptions & { bigint: boolean, throwIfNoEntry?: false | undefined }): IStats | IBigIntStats;
* (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined;
* }} LStatSync
*/
/**
* @typedef {{
* (path: PathLike, callback: StatsCallback): void;
* (path: PathLike, options: (StatOptions & { bigint?: false | undefined }) | undefined, callback: StatsCallback): void;
* (path: PathLike, options: StatOptions & { bigint: true }, callback: BigIntStatsCallback): void;
* (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void;
* }} Stat
*/
/**
* @typedef {{
* (path: PathLike, options?: undefined): IStats;
* (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry: false }): IStats | undefined;
* (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry: false }): IBigIntStats | undefined;
* (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined }): IStats;
* (path: PathLike, options: StatSyncOptions & { bigint: true }): IBigIntStats;
* (path: PathLike, options: StatSyncOptions & { bigint: boolean, throwIfNoEntry?: false | undefined }): IStats | IBigIntStats;
* (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined;
* }} StatSync
*/
/**
* @typedef {{
* (path: PathLike, options: EncodingOption, callback: StringCallback): void;
* (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void;
* (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void;
* (path: PathLike, callback: StringCallback): void;
* }} RealPath
*/
/**
* @typedef {{
* (path: PathLike, options?: EncodingOption): string;
* (path: PathLike, options: BufferEncodingOption): Buffer;
* (path: PathLike, options?: EncodingOption): string | Buffer;
* }} RealPathSync
*/
/**
* @typedef {Object} FileSystem
* @property {ReadFile} readFile
* @property {Readdir} readdir
* @property {ReadJson=} readJson
* @property {Readlink} readlink
* @property {LStat=} lstat
* @property {Stat} stat
* @property {RealPath=} realpath
*/
/**
* @typedef {Object} SyncFileSystem
* @property {ReadFileSync} readFileSync
* @property {ReaddirSync} readdirSync
* @property {ReadJsonSync=} readJsonSync
* @property {ReadlinkSync} readlinkSync
* @property {LStatSync=} lstatSync
* @property {StatSync} statSync
* @property {RealPathSync=} realpathSync
*/
/**
* @typedef {Object} ParsedIdentifier
* @property {string} request
* @property {string} query
* @property {string} fragment
* @property {boolean} directory
* @property {boolean} module
* @property {boolean} file
* @property {boolean} internal
*/
/** @typedef {string | number | boolean | null} JsonPrimitive */
/** @typedef {JsonValue[]} JsonArray */
/** @typedef {JsonPrimitive | JsonObject | JsonArray} JsonValue */
/** @typedef {{[Key in string]: JsonValue} & {[Key in string]?: JsonValue | undefined}} JsonObject */
/**
* @typedef {Object} BaseResolveRequest
* @property {string | false} path
* @property {object=} context
* @property {string=} descriptionFilePath
* @property {string=} descriptionFileRoot
* @property {JsonObject=} descriptionFileData
* @property {string=} relativePath
* @property {boolean=} ignoreSymlinks
* @property {boolean=} fullySpecified
* @property {string=} __innerRequest
* @property {string=} __innerRequest_request
* @property {string=} __innerRequest_relativePath
*/
/** @typedef {BaseResolveRequest & Partial<ParsedIdentifier>} ResolveRequest */
/**
* String with special formatting
* @typedef {string} StackEntry
*/
/**
* @template T
* @typedef {{ add: (item: T) => void }} WriteOnlySet
*/
/** @typedef {(function (ResolveRequest): void)} ResolveContextYield */
/**
* Resolve context
* @typedef {Object} ResolveContext
* @property {WriteOnlySet<string>=} contextDependencies
* @property {WriteOnlySet<string>=} fileDependencies files that was found on file system
* @property {WriteOnlySet<string>=} missingDependencies dependencies that was not found on file system
* @property {Set<StackEntry>=} stack set of hooks' calls. For instance, `resolve → parsedResolve → describedResolve`,
* @property {(function(string): void)=} log log function
* @property {ResolveContextYield=} yield yield result, if provided plugins can return several results
*/
/** @typedef {AsyncSeriesBailHook<[ResolveRequest, ResolveContext], ResolveRequest | null>} ResolveStepHook */
/**
* @typedef {Object} KnownHooks
* @property {SyncHook<[ResolveStepHook, ResolveRequest], void>} resolveStep
* @property {SyncHook<[ResolveRequest, Error]>} noResolve
* @property {ResolveStepHook} resolve
* @property {AsyncSeriesHook<[ResolveRequest, ResolveContext]>} result
*/
/**
* @typedef {{[key: string]: ResolveStepHook}} EnsuredHooks
*/
/**
* @param {string} str input string
* @returns {string} in camel case
*/
function toCamelCase(str) {
return str.replace(/-([a-z])/g, str => str.slice(1).toUpperCase());
}
class Resolver {
/**
* @param {ResolveStepHook} hook hook
* @param {ResolveRequest} request request
* @returns {StackEntry} stack entry
*/
static createStackEntry(hook, request) {
return (
hook.name +
": (" +
request.path +
") " +
(request.request || "") +
(request.query || "") +
(request.fragment || "") +
(request.directory ? " directory" : "") +
(request.module ? " module" : "")
);
}
/**
* @param {FileSystem} fileSystem a filesystem
* @param {ResolveOptions} options options
*/
constructor(fileSystem, options) {
this.fileSystem = fileSystem;
this.options = options;
/** @type {KnownHooks} */
this.hooks = {
resolveStep: new SyncHook(["hook", "request"], "resolveStep"),
noResolve: new SyncHook(["request", "error"], "noResolve"),
resolve: new AsyncSeriesBailHook(
["request", "resolveContext"],
"resolve"
),
result: new AsyncSeriesHook(["result", "resolveContext"], "result")
};
}
/**
* @param {string | ResolveStepHook} name hook name or hook itself
* @returns {ResolveStepHook} the hook
*/
ensureHook(name) {
if (typeof name !== "string") {
return name;
}
name = toCamelCase(name);
if (/^before/.test(name)) {
return /** @type {ResolveStepHook} */ (
this.ensureHook(name[6].toLowerCase() + name.slice(7)).withOptions({
stage: -10
})
);
}
if (/^after/.test(name)) {
return /** @type {ResolveStepHook} */ (
this.ensureHook(name[5].toLowerCase() + name.slice(6)).withOptions({
stage: 10
})
);
}
/** @type {ResolveStepHook} */
const hook = /** @type {KnownHooks & EnsuredHooks} */ (this.hooks)[name];
if (!hook) {
/** @type {KnownHooks & EnsuredHooks} */
(this.hooks)[name] = new AsyncSeriesBailHook(
["request", "resolveContext"],
name
);
return /** @type {KnownHooks & EnsuredHooks} */ (this.hooks)[name];
}
return hook;
}
/**
* @param {string | ResolveStepHook} name hook name or hook itself
* @returns {ResolveStepHook} the hook
*/
getHook(name) {
if (typeof name !== "string") {
return name;
}
name = toCamelCase(name);
if (/^before/.test(name)) {
return /** @type {ResolveStepHook} */ (
this.getHook(name[6].toLowerCase() + name.slice(7)).withOptions({
stage: -10
})
);
}
if (/^after/.test(name)) {
return /** @type {ResolveStepHook} */ (
this.getHook(name[5].toLowerCase() + name.slice(6)).withOptions({
stage: 10
})
);
}
/** @type {ResolveStepHook} */
const hook = /** @type {KnownHooks & EnsuredHooks} */ (this.hooks)[name];
if (!hook) {
throw new Error(`Hook ${name} doesn't exist`);
}
return hook;
}
/**
* @param {object} context context information object
* @param {string} path context path
* @param {string} request request string
* @returns {string | false} result
*/
resolveSync(context, path, request) {
/** @type {Error | null | undefined} */
let err = undefined;
/** @type {string | false | undefined} */
let result = undefined;
let sync = false;
this.resolve(context, path, request, {}, (e, r) => {
err = e;
result = r;
sync = true;
});
if (!sync) {
throw new Error(
"Cannot 'resolveSync' because the fileSystem is not sync. Use 'resolve'!"
);
}
if (err) throw err;
if (result === undefined) throw new Error("No result");
return result;
}
/**
* @param {object} context context information object
* @param {string} path context path
* @param {string} request request string
* @param {ResolveContext} resolveContext resolve context
* @param {ResolveCallback} callback callback function
* @returns {void}
*/
resolve(context, path, request, resolveContext, callback) {
if (!context || typeof context !== "object")
return callback(new Error("context argument is not an object"));
if (typeof path !== "string")
return callback(new Error("path argument is not a string"));
if (typeof request !== "string")
return callback(new Error("request argument is not a string"));
if (!resolveContext)
return callback(new Error("resolveContext argument is not set"));
/** @type {ResolveRequest} */
const obj = {
context: context,
path: path,
request: request
};
/** @type {ResolveContextYield | undefined} */
let yield_;
let yieldCalled = false;
/** @type {ResolveContextYield | undefined} */
let finishYield;
if (typeof resolveContext.yield === "function") {
const old = resolveContext.yield;
/**
* @param {ResolveRequest} obj object
*/
yield_ = obj => {
old(obj);
yieldCalled = true;
};
/**
* @param {ResolveRequest} result result
* @returns {void}
*/
finishYield = result => {
if (result) {
/** @type {ResolveContextYield} */ (yield_)(result);
}
callback(null);
};
}
const message = `resolve '${request}' in '${path}'`;
/**
* @param {ResolveRequest} result result
* @returns {void}
*/
const finishResolved = result => {
return callback(
null,
result.path === false
? false
: `${result.path.replace(/#/g, "\0#")}${
result.query ? result.query.replace(/#/g, "\0#") : ""
}${result.fragment || ""}`,
result
);
};
/**
* @param {string[]} log logs
* @returns {void}
*/
const finishWithoutResolve = log => {
/**
* @type {ErrorWithDetail}
*/
const error = new Error("Can't " + message);
error.details = log.join("\n");
this.hooks.noResolve.call(obj, error);
return callback(error);
};
if (resolveContext.log) {
// We need log anyway to capture it in case of an error
const parentLog = resolveContext.log;
/** @type {string[]} */
const log = [];
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: msg => {
parentLog(msg);
log.push(msg);
},
yield: yield_,
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: resolveContext.stack
},
(err, result) => {
if (err) return callback(err);
if (yieldCalled || (result && yield_)) {
return /** @type {ResolveContextYield} */ (finishYield)(
/** @type {ResolveRequest} */ (result)
);
}
if (result) return finishResolved(result);
return finishWithoutResolve(log);
}
);
} else {
// Try to resolve assuming there is no error
// We don't log stuff in this case
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: undefined,
yield: yield_,
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: resolveContext.stack
},
(err, result) => {
if (err) return callback(err);
if (yieldCalled || (result && yield_)) {
return /** @type {ResolveContextYield} */ (finishYield)(
/** @type {ResolveRequest} */ (result)
);
}
if (result) return finishResolved(result);
// log is missing for the error details
// so we redo the resolving for the log info
// this is more expensive to the success case
// is assumed by default
/** @type {string[]} */
const log = [];
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: msg => log.push(msg),
yield: yield_,
stack: resolveContext.stack
},
(err, result) => {
if (err) return callback(err);
// In a case that there is a race condition and yield will be called
if (yieldCalled || (result && yield_)) {
return /** @type {ResolveContextYield} */ (finishYield)(
/** @type {ResolveRequest} */ (result)
);
}
return finishWithoutResolve(log);
}
);
}
);
}
}
/**
* @param {ResolveStepHook} hook hook
* @param {ResolveRequest} request request
* @param {null|string} message string
* @param {ResolveContext} resolveContext resolver context
* @param {(err?: null|Error, result?: ResolveRequest) => void} callback callback
* @returns {void}
*/
doResolve(hook, request, message, resolveContext, callback) {
const stackEntry = Resolver.createStackEntry(hook, request);
/** @type {Set<string> | undefined} */
let newStack;
if (resolveContext.stack) {
newStack = new Set(resolveContext.stack);
if (resolveContext.stack.has(stackEntry)) {
/**
* Prevent recursion
* @type {Error & {recursion?: boolean}}
*/
const recursionError = new Error(
"Recursion in resolving\nStack:\n " +
Array.from(newStack).join("\n ")
);
recursionError.recursion = true;
if (resolveContext.log)
resolveContext.log("abort resolving because of recursion");
return callback(recursionError);
}
newStack.add(stackEntry);
} else {
// creating a set with new Set([item])
// allocates a new array that has to be garbage collected
// this is an EXTREMELY hot path, so let's avoid it
newStack = new Set();
newStack.add(stackEntry);
}
this.hooks.resolveStep.call(hook, request);
if (hook.isUsed()) {
const innerContext = createInnerContext(
{
log: resolveContext.log,
yield: resolveContext.yield,
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: newStack
},
message
);
return hook.callAsync(request, innerContext, (err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
callback();
});
} else {
callback();
}
}
/**
* @param {string} identifier identifier
* @returns {ParsedIdentifier} parsed identifier
*/
parse(identifier) {
const part = {
request: "",
query: "",
fragment: "",
module: false,
directory: false,
file: false,
internal: false
};
const parsedIdentifier = parseIdentifier(identifier);
if (!parsedIdentifier) return part;
[part.request, part.query, part.fragment] = parsedIdentifier;
if (part.request.length > 0) {
part.internal = this.isPrivate(identifier);
part.module = this.isModule(part.request);
part.directory = this.isDirectory(part.request);
if (part.directory) {
part.request = part.request.slice(0, -1);
}
}
return part;
}
/**
* @param {string} path path
* @returns {boolean} true, if the path is a module
*/
isModule(path) {
return getType(path) === PathType.Normal;
}
/**
* @param {string} path path
* @returns {boolean} true, if the path is private
*/
isPrivate(path) {
return getType(path) === PathType.Internal;
}
/**
* @param {string} path a path
* @returns {boolean} true, if the path is a directory path
*/
isDirectory(path) {
return path.endsWith("/");
}
/**
* @param {string} path path
* @param {string} request request
* @returns {string} joined path
*/
join(path, request) {
return join(path, request);
}
/**
* @param {string} path path
* @returns {string} normalized path
*/
normalize(path) {
return normalize(path);
}
}
module.exports = Resolver;

View File

@ -0,0 +1,728 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const versions = require("process").versions;
const Resolver = require("./Resolver");
const { getType, PathType } = require("./util/path");
const SyncAsyncFileSystemDecorator = require("./SyncAsyncFileSystemDecorator");
const AliasFieldPlugin = require("./AliasFieldPlugin");
const AliasPlugin = require("./AliasPlugin");
const AppendPlugin = require("./AppendPlugin");
const ConditionalPlugin = require("./ConditionalPlugin");
const DescriptionFilePlugin = require("./DescriptionFilePlugin");
const DirectoryExistsPlugin = require("./DirectoryExistsPlugin");
const ExportsFieldPlugin = require("./ExportsFieldPlugin");
const ExtensionAliasPlugin = require("./ExtensionAliasPlugin");
const FileExistsPlugin = require("./FileExistsPlugin");
const ImportsFieldPlugin = require("./ImportsFieldPlugin");
const JoinRequestPartPlugin = require("./JoinRequestPartPlugin");
const JoinRequestPlugin = require("./JoinRequestPlugin");
const MainFieldPlugin = require("./MainFieldPlugin");
const ModulesInHierarchicalDirectoriesPlugin = require("./ModulesInHierarchicalDirectoriesPlugin");
const ModulesInRootPlugin = require("./ModulesInRootPlugin");
const NextPlugin = require("./NextPlugin");
const ParsePlugin = require("./ParsePlugin");
const PnpPlugin = require("./PnpPlugin");
const RestrictionsPlugin = require("./RestrictionsPlugin");
const ResultPlugin = require("./ResultPlugin");
const RootsPlugin = require("./RootsPlugin");
const SelfReferencePlugin = require("./SelfReferencePlugin");
const SymlinkPlugin = require("./SymlinkPlugin");
const TryNextPlugin = require("./TryNextPlugin");
const UnsafeCachePlugin = require("./UnsafeCachePlugin");
const UseFilePlugin = require("./UseFilePlugin");
/** @typedef {import("./AliasPlugin").AliasOption} AliasOptionEntry */
/** @typedef {import("./ExtensionAliasPlugin").ExtensionAliasOption} ExtensionAliasOption */
/** @typedef {import("./PnpPlugin").PnpApiImpl} PnpApi */
/** @typedef {import("./Resolver").EnsuredHooks} EnsuredHooks */
/** @typedef {import("./Resolver").FileSystem} FileSystem */
/** @typedef {import("./Resolver").KnownHooks} KnownHooks */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */
/** @typedef {string|string[]|false} AliasOptionNewRequest */
/** @typedef {{[k: string]: AliasOptionNewRequest}} AliasOptions */
/** @typedef {{[k: string]: string|string[] }} ExtensionAliasOptions */
/** @typedef {false | 0 | "" | null | undefined} Falsy */
/** @typedef {{apply: function(Resolver): void} | (function(this: Resolver, Resolver): void) | Falsy} Plugin */
/**
* @typedef {Object} UserResolveOptions
* @property {(AliasOptions | AliasOptionEntry[])=} alias A list of module alias configurations or an object which maps key to value
* @property {(AliasOptions | AliasOptionEntry[])=} fallback A list of module alias configurations or an object which maps key to value, applied only after modules option
* @property {ExtensionAliasOptions=} extensionAlias An object which maps extension to extension aliases
* @property {(string | string[])[]=} aliasFields A list of alias fields in description files
* @property {(function(ResolveRequest): boolean)=} cachePredicate A function which decides whether a request should be cached or not. An object is passed with at least `path` and `request` properties.
* @property {boolean=} cacheWithContext Whether or not the unsafeCache should include request context as part of the cache key.
* @property {string[]=} descriptionFiles A list of description files to read from
* @property {string[]=} conditionNames A list of exports field condition names.
* @property {boolean=} enforceExtension Enforce that a extension from extensions must be used
* @property {(string | string[])[]=} exportsFields A list of exports fields in description files
* @property {(string | string[])[]=} importsFields A list of imports fields in description files
* @property {string[]=} extensions A list of extensions which should be tried for files
* @property {FileSystem} fileSystem The file system which should be used
* @property {(object | boolean)=} unsafeCache Use this cache object to unsafely cache the successful requests
* @property {boolean=} symlinks Resolve symlinks to their symlinked location
* @property {Resolver=} resolver A prepared Resolver to which the plugins are attached
* @property {string[] | string=} modules A list of directories to resolve modules from, can be absolute path or folder name
* @property {(string | string[] | {name: string | string[], forceRelative: boolean})[]=} mainFields A list of main fields in description files
* @property {string[]=} mainFiles A list of main files in directories
* @property {Plugin[]=} plugins A list of additional resolve plugins which should be applied
* @property {PnpApi | null=} pnpApi A PnP API that should be used - null is "never", undefined is "auto"
* @property {string[]=} roots A list of root paths
* @property {boolean=} fullySpecified The request is already fully specified and no extensions or directories are resolved for it
* @property {boolean=} resolveToContext Resolve to a context instead of a file
* @property {(string|RegExp)[]=} restrictions A list of resolve restrictions
* @property {boolean=} useSyncFileSystemCalls Use only the sync constraints of the file system calls
* @property {boolean=} preferRelative Prefer to resolve module requests as relative requests before falling back to modules
* @property {boolean=} preferAbsolute Prefer to resolve server-relative urls as absolute paths before falling back to resolve in roots
*/
/**
* @typedef {Object} ResolveOptions
* @property {AliasOptionEntry[]} alias
* @property {AliasOptionEntry[]} fallback
* @property {Set<string | string[]>} aliasFields
* @property {ExtensionAliasOption[]} extensionAlias
* @property {(function(ResolveRequest): boolean)} cachePredicate
* @property {boolean} cacheWithContext
* @property {Set<string>} conditionNames A list of exports field condition names.
* @property {string[]} descriptionFiles
* @property {boolean} enforceExtension
* @property {Set<string | string[]>} exportsFields
* @property {Set<string | string[]>} importsFields
* @property {Set<string>} extensions
* @property {FileSystem} fileSystem
* @property {object | false} unsafeCache
* @property {boolean} symlinks
* @property {Resolver=} resolver
* @property {Array<string | string[]>} modules
* @property {{name: string[], forceRelative: boolean}[]} mainFields
* @property {Set<string>} mainFiles
* @property {Plugin[]} plugins
* @property {PnpApi | null} pnpApi
* @property {Set<string>} roots
* @property {boolean} fullySpecified
* @property {boolean} resolveToContext
* @property {Set<string|RegExp>} restrictions
* @property {boolean} preferRelative
* @property {boolean} preferAbsolute
*/
/**
* @param {PnpApi | null=} option option
* @returns {PnpApi | null} processed option
*/
function processPnpApiOption(option) {
if (
option === undefined &&
/** @type {NodeJS.ProcessVersions & {pnp: string}} */ versions.pnp
) {
const _findPnpApi =
/** @type {function(string): PnpApi | null}} */
(
// @ts-ignore
require("module").findPnpApi
);
if (_findPnpApi) {
return {
resolveToUnqualified(request, issuer, opts) {
const pnpapi = _findPnpApi(issuer);
if (!pnpapi) {
// Issuer isn't managed by PnP
return null;
}
return pnpapi.resolveToUnqualified(request, issuer, opts);
}
};
}
}
return option || null;
}
/**
* @param {AliasOptions | AliasOptionEntry[] | undefined} alias alias
* @returns {AliasOptionEntry[]} normalized aliases
*/
function normalizeAlias(alias) {
return typeof alias === "object" && !Array.isArray(alias) && alias !== null
? Object.keys(alias).map(key => {
/** @type {AliasOptionEntry} */
const obj = { name: key, onlyModule: false, alias: alias[key] };
if (/\$$/.test(key)) {
obj.onlyModule = true;
obj.name = key.slice(0, -1);
}
return obj;
})
: /** @type {Array<AliasOptionEntry>} */ (alias) || [];
}
/**
* @param {UserResolveOptions} options input options
* @returns {ResolveOptions} output options
*/
function createOptions(options) {
const mainFieldsSet = new Set(options.mainFields || ["main"]);
/** @type {ResolveOptions["mainFields"]} */
const mainFields = [];
for (const item of mainFieldsSet) {
if (typeof item === "string") {
mainFields.push({
name: [item],
forceRelative: true
});
} else if (Array.isArray(item)) {
mainFields.push({
name: item,
forceRelative: true
});
} else {
mainFields.push({
name: Array.isArray(item.name) ? item.name : [item.name],
forceRelative: item.forceRelative
});
}
}
return {
alias: normalizeAlias(options.alias),
fallback: normalizeAlias(options.fallback),
aliasFields: new Set(options.aliasFields),
cachePredicate:
options.cachePredicate ||
function () {
return true;
},
cacheWithContext:
typeof options.cacheWithContext !== "undefined"
? options.cacheWithContext
: true,
exportsFields: new Set(options.exportsFields || ["exports"]),
importsFields: new Set(options.importsFields || ["imports"]),
conditionNames: new Set(options.conditionNames),
descriptionFiles: Array.from(
new Set(options.descriptionFiles || ["package.json"])
),
enforceExtension:
options.enforceExtension === undefined
? options.extensions && options.extensions.includes("")
? true
: false
: options.enforceExtension,
extensions: new Set(options.extensions || [".js", ".json", ".node"]),
extensionAlias: options.extensionAlias
? Object.keys(options.extensionAlias).map(k => ({
extension: k,
alias: /** @type {ExtensionAliasOptions} */ (options.extensionAlias)[
k
]
}))
: [],
fileSystem: options.useSyncFileSystemCalls
? new SyncAsyncFileSystemDecorator(
/** @type {SyncFileSystem} */ (
/** @type {unknown} */ (options.fileSystem)
)
)
: options.fileSystem,
unsafeCache:
options.unsafeCache && typeof options.unsafeCache !== "object"
? {}
: options.unsafeCache || false,
symlinks: typeof options.symlinks !== "undefined" ? options.symlinks : true,
resolver: options.resolver,
modules: mergeFilteredToArray(
Array.isArray(options.modules)
? options.modules
: options.modules
? [options.modules]
: ["node_modules"],
item => {
const type = getType(item);
return type === PathType.Normal || type === PathType.Relative;
}
),
mainFields,
mainFiles: new Set(options.mainFiles || ["index"]),
plugins: options.plugins || [],
pnpApi: processPnpApiOption(options.pnpApi),
roots: new Set(options.roots || undefined),
fullySpecified: options.fullySpecified || false,
resolveToContext: options.resolveToContext || false,
preferRelative: options.preferRelative || false,
preferAbsolute: options.preferAbsolute || false,
restrictions: new Set(options.restrictions)
};
}
/**
* @param {UserResolveOptions} options resolve options
* @returns {Resolver} created resolver
*/
exports.createResolver = function (options) {
const normalizedOptions = createOptions(options);
const {
alias,
fallback,
aliasFields,
cachePredicate,
cacheWithContext,
conditionNames,
descriptionFiles,
enforceExtension,
exportsFields,
extensionAlias,
importsFields,
extensions,
fileSystem,
fullySpecified,
mainFields,
mainFiles,
modules,
plugins: userPlugins,
pnpApi,
resolveToContext,
preferRelative,
preferAbsolute,
symlinks,
unsafeCache,
resolver: customResolver,
restrictions,
roots
} = normalizedOptions;
const plugins = userPlugins.slice();
const resolver = customResolver
? customResolver
: new Resolver(fileSystem, normalizedOptions);
//// pipeline ////
resolver.ensureHook("resolve");
resolver.ensureHook("internalResolve");
resolver.ensureHook("newInternalResolve");
resolver.ensureHook("parsedResolve");
resolver.ensureHook("describedResolve");
resolver.ensureHook("rawResolve");
resolver.ensureHook("normalResolve");
resolver.ensureHook("internal");
resolver.ensureHook("rawModule");
resolver.ensureHook("alternateRawModule");
resolver.ensureHook("module");
resolver.ensureHook("resolveAsModule");
resolver.ensureHook("undescribedResolveInPackage");
resolver.ensureHook("resolveInPackage");
resolver.ensureHook("resolveInExistingDirectory");
resolver.ensureHook("relative");
resolver.ensureHook("describedRelative");
resolver.ensureHook("directory");
resolver.ensureHook("undescribedExistingDirectory");
resolver.ensureHook("existingDirectory");
resolver.ensureHook("undescribedRawFile");
resolver.ensureHook("rawFile");
resolver.ensureHook("file");
resolver.ensureHook("finalFile");
resolver.ensureHook("existingFile");
resolver.ensureHook("resolved");
// TODO remove in next major
// cspell:word Interal
// Backward-compat
// @ts-ignore
resolver.hooks.newInteralResolve = resolver.hooks.newInternalResolve;
// resolve
for (const { source, resolveOptions } of [
{ source: "resolve", resolveOptions: { fullySpecified } },
{ source: "internal-resolve", resolveOptions: { fullySpecified: false } }
]) {
if (unsafeCache) {
plugins.push(
new UnsafeCachePlugin(
source,
cachePredicate,
/** @type {import("./UnsafeCachePlugin").Cache} */ (unsafeCache),
cacheWithContext,
`new-${source}`
)
);
plugins.push(
new ParsePlugin(`new-${source}`, resolveOptions, "parsed-resolve")
);
} else {
plugins.push(new ParsePlugin(source, resolveOptions, "parsed-resolve"));
}
}
// parsed-resolve
plugins.push(
new DescriptionFilePlugin(
"parsed-resolve",
descriptionFiles,
false,
"described-resolve"
)
);
plugins.push(new NextPlugin("after-parsed-resolve", "described-resolve"));
// described-resolve
plugins.push(new NextPlugin("described-resolve", "raw-resolve"));
if (fallback.length > 0) {
plugins.push(
new AliasPlugin("described-resolve", fallback, "internal-resolve")
);
}
// raw-resolve
if (alias.length > 0) {
plugins.push(new AliasPlugin("raw-resolve", alias, "internal-resolve"));
}
aliasFields.forEach(item => {
plugins.push(new AliasFieldPlugin("raw-resolve", item, "internal-resolve"));
});
extensionAlias.forEach(item =>
plugins.push(
new ExtensionAliasPlugin("raw-resolve", item, "normal-resolve")
)
);
plugins.push(new NextPlugin("raw-resolve", "normal-resolve"));
// normal-resolve
if (preferRelative) {
plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative"));
}
plugins.push(
new ConditionalPlugin(
"after-normal-resolve",
{ module: true },
"resolve as module",
false,
"raw-module"
)
);
plugins.push(
new ConditionalPlugin(
"after-normal-resolve",
{ internal: true },
"resolve as internal import",
false,
"internal"
)
);
if (preferAbsolute) {
plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative"));
}
if (roots.size > 0) {
plugins.push(new RootsPlugin("after-normal-resolve", roots, "relative"));
}
if (!preferRelative && !preferAbsolute) {
plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative"));
}
// internal
importsFields.forEach(importsField => {
plugins.push(
new ImportsFieldPlugin(
"internal",
conditionNames,
importsField,
"relative",
"internal-resolve"
)
);
});
// raw-module
exportsFields.forEach(exportsField => {
plugins.push(
new SelfReferencePlugin("raw-module", exportsField, "resolve-as-module")
);
});
modules.forEach(item => {
if (Array.isArray(item)) {
if (item.includes("node_modules") && pnpApi) {
plugins.push(
new ModulesInHierarchicalDirectoriesPlugin(
"raw-module",
item.filter(i => i !== "node_modules"),
"module"
)
);
plugins.push(
new PnpPlugin(
"raw-module",
pnpApi,
"undescribed-resolve-in-package",
"alternate-raw-module"
)
);
plugins.push(
new ModulesInHierarchicalDirectoriesPlugin(
"alternate-raw-module",
["node_modules"],
"module"
)
);
} else {
plugins.push(
new ModulesInHierarchicalDirectoriesPlugin(
"raw-module",
item,
"module"
)
);
}
} else {
plugins.push(new ModulesInRootPlugin("raw-module", item, "module"));
}
});
// module
plugins.push(new JoinRequestPartPlugin("module", "resolve-as-module"));
// resolve-as-module
if (!resolveToContext) {
plugins.push(
new ConditionalPlugin(
"resolve-as-module",
{ directory: false, request: "." },
"single file module",
true,
"undescribed-raw-file"
)
);
}
plugins.push(
new DirectoryExistsPlugin(
"resolve-as-module",
"undescribed-resolve-in-package"
)
);
// undescribed-resolve-in-package
plugins.push(
new DescriptionFilePlugin(
"undescribed-resolve-in-package",
descriptionFiles,
false,
"resolve-in-package"
)
);
plugins.push(
new NextPlugin("after-undescribed-resolve-in-package", "resolve-in-package")
);
// resolve-in-package
exportsFields.forEach(exportsField => {
plugins.push(
new ExportsFieldPlugin(
"resolve-in-package",
conditionNames,
exportsField,
"relative"
)
);
});
plugins.push(
new NextPlugin("resolve-in-package", "resolve-in-existing-directory")
);
// resolve-in-existing-directory
plugins.push(
new JoinRequestPlugin("resolve-in-existing-directory", "relative")
);
// relative
plugins.push(
new DescriptionFilePlugin(
"relative",
descriptionFiles,
true,
"described-relative"
)
);
plugins.push(new NextPlugin("after-relative", "described-relative"));
// described-relative
if (resolveToContext) {
plugins.push(new NextPlugin("described-relative", "directory"));
} else {
plugins.push(
new ConditionalPlugin(
"described-relative",
{ directory: false },
null,
true,
"raw-file"
)
);
plugins.push(
new ConditionalPlugin(
"described-relative",
{ fullySpecified: false },
"as directory",
true,
"directory"
)
);
}
// directory
plugins.push(
new DirectoryExistsPlugin("directory", "undescribed-existing-directory")
);
if (resolveToContext) {
// undescribed-existing-directory
plugins.push(new NextPlugin("undescribed-existing-directory", "resolved"));
} else {
// undescribed-existing-directory
plugins.push(
new DescriptionFilePlugin(
"undescribed-existing-directory",
descriptionFiles,
false,
"existing-directory"
)
);
mainFiles.forEach(item => {
plugins.push(
new UseFilePlugin(
"undescribed-existing-directory",
item,
"undescribed-raw-file"
)
);
});
// described-existing-directory
mainFields.forEach(item => {
plugins.push(
new MainFieldPlugin(
"existing-directory",
item,
"resolve-in-existing-directory"
)
);
});
mainFiles.forEach(item => {
plugins.push(
new UseFilePlugin("existing-directory", item, "undescribed-raw-file")
);
});
// undescribed-raw-file
plugins.push(
new DescriptionFilePlugin(
"undescribed-raw-file",
descriptionFiles,
true,
"raw-file"
)
);
plugins.push(new NextPlugin("after-undescribed-raw-file", "raw-file"));
// raw-file
plugins.push(
new ConditionalPlugin(
"raw-file",
{ fullySpecified: true },
null,
false,
"file"
)
);
if (!enforceExtension) {
plugins.push(new TryNextPlugin("raw-file", "no extension", "file"));
}
extensions.forEach(item => {
plugins.push(new AppendPlugin("raw-file", item, "file"));
});
// file
if (alias.length > 0)
plugins.push(new AliasPlugin("file", alias, "internal-resolve"));
aliasFields.forEach(item => {
plugins.push(new AliasFieldPlugin("file", item, "internal-resolve"));
});
plugins.push(new NextPlugin("file", "final-file"));
// final-file
plugins.push(new FileExistsPlugin("final-file", "existing-file"));
// existing-file
if (symlinks)
plugins.push(new SymlinkPlugin("existing-file", "existing-file"));
plugins.push(new NextPlugin("existing-file", "resolved"));
}
const resolved =
/** @type {KnownHooks & EnsuredHooks} */
(resolver.hooks).resolved;
// resolved
if (restrictions.size > 0) {
plugins.push(new RestrictionsPlugin(resolved, restrictions));
}
plugins.push(new ResultPlugin(resolved));
//// RESOLVER ////
for (const plugin of plugins) {
if (typeof plugin === "function") {
/** @type {function(this: Resolver, Resolver): void} */
(plugin).call(resolver, resolver);
} else if (plugin) {
plugin.apply(resolver);
}
}
return resolver;
};
/**
* Merging filtered elements
* @param {string[]} array source array
* @param {function(string): boolean} filter predicate
* @returns {Array<string | string[]>} merge result
*/
function mergeFilteredToArray(array, filter) {
/** @type {Array<string | string[]>} */
const result = [];
const set = new Set(array);
for (const item of set) {
if (filter(item)) {
const lastElement =
result.length > 0 ? result[result.length - 1] : undefined;
if (Array.isArray(lastElement)) {
lastElement.push(item);
} else {
result.push([item]);
}
} else {
result.push(item);
}
}
return result;
}

View File

@ -0,0 +1,70 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
const slashCode = "/".charCodeAt(0);
const backslashCode = "\\".charCodeAt(0);
/**
* @param {string} path path
* @param {string} parent parent path
* @returns {boolean} true, if path is inside of parent
*/
const isInside = (path, parent) => {
if (!path.startsWith(parent)) return false;
if (path.length === parent.length) return true;
const charCode = path.charCodeAt(parent.length);
return charCode === slashCode || charCode === backslashCode;
};
module.exports = class RestrictionsPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {Set<string | RegExp>} restrictions restrictions
*/
constructor(source, restrictions) {
this.source = source;
this.restrictions = restrictions;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
resolver
.getHook(this.source)
.tapAsync("RestrictionsPlugin", (request, resolveContext, callback) => {
if (typeof request.path === "string") {
const path = request.path;
for (const rule of this.restrictions) {
if (typeof rule === "string") {
if (!isInside(path, rule)) {
if (resolveContext.log) {
resolveContext.log(
`${path} is not inside of the restriction ${rule}`
);
}
return callback(null, null);
}
} else if (!rule.test(path)) {
if (resolveContext.log) {
resolveContext.log(
`${path} doesn't match the restriction ${rule}`
);
}
return callback(null, null);
}
}
}
callback();
});
}
};

View File

@ -0,0 +1,42 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class ResultPlugin {
/**
* @param {ResolveStepHook} source source
*/
constructor(source) {
this.source = source;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
this.source.tapAsync(
"ResultPlugin",
(request, resolverContext, callback) => {
const obj = { ...request };
if (resolverContext.log)
resolverContext.log("reporting result " + obj.path);
resolver.hooks.result.callAsync(obj, resolverContext, err => {
if (err) return callback(err);
if (typeof resolverContext.yield === "function") {
resolverContext.yield(obj);
callback(null, null);
} else {
callback(null, obj);
}
});
}
);
}
};

View File

@ -0,0 +1,69 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const forEachBail = require("./forEachBail");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
class RootsPlugin {
/**
* @param {string | ResolveStepHook} source source hook
* @param {Set<string>} roots roots
* @param {string | ResolveStepHook} target target hook
*/
constructor(source, roots, target) {
this.roots = Array.from(roots);
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("RootsPlugin", (request, resolveContext, callback) => {
const req = request.request;
if (!req) return callback();
if (!req.startsWith("/")) return callback();
forEachBail(
this.roots,
/**
* @param {string} root root
* @param {(err?: null|Error, result?: null|ResolveRequest) => void} callback callback
* @returns {void}
*/
(root, callback) => {
const path = resolver.join(root, req.slice(1));
/** @type {ResolveRequest} */
const obj = {
...request,
path,
relativePath: request.relativePath && path
};
resolver.doResolve(
target,
obj,
`root path ${root}`,
resolveContext,
callback
);
},
callback
);
});
}
}
module.exports = RootsPlugin;

View File

@ -0,0 +1,82 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").JsonObject} JsonObject */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
const slashCode = "/".charCodeAt(0);
module.exports = class SelfReferencePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | string[]} fieldNamePath name path
* @param {string | ResolveStepHook} target target
*/
constructor(source, fieldNamePath, target) {
this.source = source;
this.target = target;
this.fieldName = fieldNamePath;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("SelfReferencePlugin", (request, resolveContext, callback) => {
if (!request.descriptionFilePath) return callback();
const req = request.request;
if (!req) return callback();
// Feature is only enabled when an exports field is present
const exportsField = DescriptionFileUtils.getField(
/** @type {JsonObject} */ (request.descriptionFileData),
this.fieldName
);
if (!exportsField) return callback();
const name = DescriptionFileUtils.getField(
/** @type {JsonObject} */ (request.descriptionFileData),
"name"
);
if (typeof name !== "string") return callback();
if (
req.startsWith(name) &&
(req.length === name.length ||
req.charCodeAt(name.length) === slashCode)
) {
const remainingRequest = `.${req.slice(name.length)}`;
/** @type {ResolveRequest} */
const obj = {
...request,
request: remainingRequest,
path: /** @type {string} */ (request.descriptionFileRoot),
relativePath: "."
};
resolver.doResolve(
target,
obj,
"self reference",
resolveContext,
callback
);
} else {
return callback();
}
});
}
};

View File

@ -0,0 +1,100 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
const getPaths = require("./getPaths");
const { getType, PathType } = require("./util/path");
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class SymlinkPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string | ResolveStepHook} target target
*/
constructor(source, target) {
this.source = source;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
const fs = resolver.fileSystem;
resolver
.getHook(this.source)
.tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
if (request.ignoreSymlinks) return callback();
const pathsResult = getPaths(/** @type {string} */ (request.path));
const pathSegments = pathsResult.segments;
const paths = pathsResult.paths;
let containsSymlink = false;
let idx = -1;
forEachBail(
paths,
/**
* @param {string} path path
* @param {(err?: null|Error, result?: null|number) => void} callback callback
* @returns {void}
*/
(path, callback) => {
idx++;
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(path);
fs.readlink(path, (err, result) => {
if (!err && result) {
pathSegments[idx] = /** @type {string} */ (result);
containsSymlink = true;
// Shortcut when absolute symlink found
const resultType = getType(result.toString());
if (
resultType === PathType.AbsoluteWin ||
resultType === PathType.AbsolutePosix
) {
return callback(null, idx);
}
}
callback();
});
},
/**
* @param {null|Error} [err] error
* @param {null|number} [idx] result
* @returns {void}
*/
(err, idx) => {
if (!containsSymlink) return callback();
const resultSegments =
typeof idx === "number"
? pathSegments.slice(0, idx + 1)
: pathSegments.slice();
const result = resultSegments.reduceRight((a, b) => {
return resolver.join(a, b);
});
/** @type {ResolveRequest} */
const obj = {
...request,
path: result
};
resolver.doResolve(
target,
obj,
"resolved symlink to " + result,
resolveContext,
callback
);
}
);
});
}
};

View File

@ -0,0 +1,220 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver").FileSystem} FileSystem */
/** @typedef {import("./Resolver").ReaddirStringCallback} ReaddirStringCallback */
/** @typedef {import("./Resolver").StringCallback} StringCallback */
/** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */
/**
* @param {SyncFileSystem} fs file system implementation
* @constructor
*/
function SyncAsyncFileSystemDecorator(fs) {
this.fs = fs;
this.lstat = undefined;
this.lstatSync = undefined;
const lstatSync = fs.lstatSync;
if (lstatSync) {
this.lstat =
/** @type {FileSystem["lstat"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? lstatSync.call(fs, arg, options)
: lstatSync.call(fs, arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.lstatSync =
/** @type {SyncFileSystem["lstatSync"]} */
((arg, options) => lstatSync.call(fs, arg, options));
}
this.stat =
/** @type {FileSystem["stat"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? fs.statSync(arg, options)
: fs.statSync(arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.statSync =
/** @type {SyncFileSystem["statSync"]} */
((arg, options) => fs.statSync(arg, options));
this.readdir =
/** @type {FileSystem["readdir"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? fs.readdirSync(
arg,
/** @type {Exclude<Parameters<FileSystem["readdir"]>[1], ReaddirStringCallback>} */
(options)
)
: fs.readdirSync(arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.readdirSync =
/** @type {SyncFileSystem["readdirSync"]} */
(
(arg, options) =>
fs.readdirSync(
arg,
/** @type {Parameters<SyncFileSystem["readdirSync"]>[1]} */ (options)
)
);
this.readFile =
/** @type {FileSystem["readFile"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? fs.readFileSync(arg, options)
: fs.readFileSync(arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.readFileSync =
/** @type {SyncFileSystem["readFileSync"]} */
((arg, options) => fs.readFileSync(arg, options));
this.readlink =
/** @type {FileSystem["readlink"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? fs.readlinkSync(
arg,
/** @type {Exclude<Parameters<FileSystem["readlink"]>[1], StringCallback>} */
(options)
)
: fs.readlinkSync(arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.readlinkSync =
/** @type {SyncFileSystem["readlinkSync"]} */
(
(arg, options) =>
fs.readlinkSync(
arg,
/** @type {Parameters<SyncFileSystem["readlinkSync"]>[1]} */ (options)
)
);
this.readJson = undefined;
this.readJsonSync = undefined;
const readJsonSync = fs.readJsonSync;
if (readJsonSync) {
this.readJson =
/** @type {FileSystem["readJson"]} */
(
(arg, callback) => {
let result;
try {
result = readJsonSync.call(fs, arg);
} catch (e) {
return callback(
/** @type {NodeJS.ErrnoException | Error | null} */ (e)
);
}
callback(null, result);
}
);
this.readJsonSync =
/** @type {SyncFileSystem["readJsonSync"]} */
(arg => readJsonSync.call(fs, arg));
}
this.realpath = undefined;
this.realpathSync = undefined;
const realpathSync = fs.realpathSync;
if (realpathSync) {
this.realpath =
/** @type {FileSystem["realpath"]} */
(
(arg, options, callback) => {
let result;
try {
result = /** @type {Function | undefined} */ (callback)
? realpathSync.call(
fs,
arg,
/** @type {Exclude<Parameters<NonNullable<FileSystem["realpath"]>>[1], StringCallback>} */
(options)
)
: realpathSync.call(fs, arg);
} catch (e) {
return (callback || options)(
/** @type {NodeJS.ErrnoException | null} */ (e)
);
}
(callback || options)(null, /** @type {any} */ (result));
}
);
this.realpathSync =
/** @type {SyncFileSystem["realpathSync"]} */
(
(arg, options) =>
realpathSync.call(
fs,
arg,
/** @type {Parameters<NonNullable<SyncFileSystem["realpathSync"]>>[1]} */
(options)
)
);
}
}
module.exports = SyncAsyncFileSystemDecorator;

View File

@ -0,0 +1,41 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class TryNextPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string} message message
* @param {string | ResolveStepHook} target target
*/
constructor(source, message, target) {
this.source = source;
this.message = message;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("TryNextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(
target,
request,
this.message,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,112 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
/** @typedef {import("./Resolver").ResolveContextYield} ResolveContextYield */
/** @typedef {{[k: string]: ResolveRequest | ResolveRequest[] | undefined}} Cache */
/**
* @param {string} type type of cache
* @param {ResolveRequest} request request
* @param {boolean} withContext cache with context?
* @returns {string} cache id
*/
function getCacheId(type, request, withContext) {
return JSON.stringify({
type,
context: withContext ? request.context : "",
path: request.path,
query: request.query,
fragment: request.fragment,
request: request.request
});
}
module.exports = class UnsafeCachePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {function(ResolveRequest): boolean} filterPredicate filterPredicate
* @param {Cache} cache cache
* @param {boolean} withContext withContext
* @param {string | ResolveStepHook} target target
*/
constructor(source, filterPredicate, cache, withContext, target) {
this.source = source;
this.filterPredicate = filterPredicate;
this.withContext = withContext;
this.cache = cache;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("UnsafeCachePlugin", (request, resolveContext, callback) => {
if (!this.filterPredicate(request)) return callback();
const isYield = typeof resolveContext.yield === "function";
const cacheId = getCacheId(
isYield ? "yield" : "default",
request,
this.withContext
);
const cacheEntry = this.cache[cacheId];
if (cacheEntry) {
if (isYield) {
const yield_ = /** @type {Function} */ (resolveContext.yield);
if (Array.isArray(cacheEntry)) {
for (const result of cacheEntry) yield_(result);
} else {
yield_(cacheEntry);
}
return callback(null, null);
}
return callback(null, /** @type {ResolveRequest} */ (cacheEntry));
}
/** @type {ResolveContextYield|undefined} */
let yieldFn;
/** @type {ResolveContextYield|undefined} */
let yield_;
/** @type {ResolveRequest[]} */
const yieldResult = [];
if (isYield) {
yieldFn = resolveContext.yield;
yield_ = result => {
yieldResult.push(result);
};
}
resolver.doResolve(
target,
request,
null,
yield_ ? { ...resolveContext, yield: yield_ } : resolveContext,
(err, result) => {
if (err) return callback(err);
if (isYield) {
if (result) yieldResult.push(result);
for (const result of yieldResult) {
/** @type {ResolveContextYield} */
(yieldFn)(result);
}
this.cache[cacheId] = yieldResult;
return callback(null, null);
}
if (result) return callback(null, (this.cache[cacheId] = result));
callback();
}
);
});
}
};

View File

@ -0,0 +1,55 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
module.exports = class UseFilePlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {string} filename filename
* @param {string | ResolveStepHook} target target
*/
constructor(source, filename, target) {
this.source = source;
this.filename = filename;
this.target = target;
}
/**
* @param {Resolver} resolver the resolver
* @returns {void}
*/
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("UseFilePlugin", (request, resolveContext, callback) => {
const filePath = resolver.join(
/** @type {string} */ (request.path),
this.filename
);
/** @type {ResolveRequest} */
const obj = {
...request,
path: filePath,
relativePath:
request.relativePath &&
resolver.join(request.relativePath, this.filename)
};
resolver.doResolve(
target,
obj,
"using path: " + filePath,
resolveContext,
callback
);
});
}
};

View File

@ -0,0 +1,46 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver").ResolveContext} ResolveContext */
/**
* @param {ResolveContext} options options for inner context
* @param {null|string} message message to log
* @returns {ResolveContext} inner context
*/
module.exports = function createInnerContext(options, message) {
let messageReported = false;
let innerLog = undefined;
if (options.log) {
if (message) {
/**
* @param {string} msg message
*/
innerLog = msg => {
if (!messageReported) {
/** @type {(function(string): void)} */
(options.log)(message);
messageReported = true;
}
/** @type {(function(string): void)} */
(options.log)(" " + msg);
};
} else {
innerLog = options.log;
}
}
return {
log: innerLog,
yield: options.yield,
fileDependencies: options.fileDependencies,
contextDependencies: options.contextDependencies,
missingDependencies: options.missingDependencies,
stack: options.stack
};
};

View File

@ -0,0 +1,50 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/**
* @template T
* @template Z
* @callback Iterator
* @param {T} item item
* @param {(err?: null|Error, result?: null|Z) => void} callback callback
* @param {number} i index
* @returns {void}
*/
/**
* @template T
* @template Z
* @param {T[]} array array
* @param {Iterator<T, Z>} iterator iterator
* @param {(err?: null|Error, result?: null|Z, i?: number) => void} callback callback after all items are iterated
* @returns {void}
*/
module.exports = function forEachBail(array, iterator, callback) {
if (array.length === 0) return callback();
let i = 0;
const next = () => {
/** @type {boolean|undefined} */
let loop = undefined;
iterator(
array[i++],
(err, result) => {
if (err || result !== undefined || i >= array.length) {
return callback(err, result, i);
}
if (loop === false) while (next());
loop = true;
},
i
);
if (!loop) loop = false;
return loop;
};
while (next());
};

View File

@ -0,0 +1,36 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/**
* @param {Resolver} resolver resolver
* @param {ResolveRequest} request string
* @returns {string} inner request
*/
module.exports = function getInnerRequest(resolver, request) {
if (
typeof request.__innerRequest === "string" &&
request.__innerRequest_request === request.request &&
request.__innerRequest_relativePath === request.relativePath
)
return request.__innerRequest;
/** @type {string|undefined} */
let innerRequest;
if (request.request) {
innerRequest = request.request;
if (/^\.\.?(?:\/|$)/.test(innerRequest) && request.relativePath) {
innerRequest = resolver.join(request.relativePath, innerRequest);
}
} else {
innerRequest = request.relativePath;
}
request.__innerRequest_request = request.request;
request.__innerRequest_relativePath = request.relativePath;
return (request.__innerRequest = /** @type {string} */ (innerRequest));
};

45
app_vue/node_modules/enhanced-resolve/lib/getPaths.js generated vendored Normal file
View File

@ -0,0 +1,45 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/**
* @param {string} path path
* @returns {{paths: string[], segments: string[]}}} paths and segments
*/
module.exports = function getPaths(path) {
if (path === "/") return { paths: ["/"], segments: [""] };
const parts = path.split(/(.*?[\\/]+)/);
const paths = [path];
const segments = [parts[parts.length - 1]];
let part = parts[parts.length - 1];
path = path.substring(0, path.length - part.length - 1);
for (let i = parts.length - 2; i > 2; i -= 2) {
paths.push(path);
part = parts[i];
path = path.substring(0, path.length - part.length) || "/";
segments.push(part.slice(0, -1));
}
part = parts[1];
segments.push(part);
paths.push(part);
return {
paths: paths,
segments: segments
};
};
/**
* @param {string} path path
* @returns {string|null} basename or null
*/
module.exports.basename = function basename(path) {
const i = path.lastIndexOf("/"),
j = path.lastIndexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if (p < 0) return null;
const s = path.slice(p + 1);
return s;
};

203
app_vue/node_modules/enhanced-resolve/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,203 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const fs = require("graceful-fs");
const CachedInputFileSystem = require("./CachedInputFileSystem");
const ResolverFactory = require("./ResolverFactory");
/** @typedef {import("./PnpPlugin").PnpApiImpl} PnpApi */
/** @typedef {import("./Resolver")} Resolver */
/** @typedef {import("./Resolver").FileSystem} FileSystem */
/** @typedef {import("./Resolver").ResolveCallback} ResolveCallback */
/** @typedef {import("./Resolver").ResolveContext} ResolveContext */
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/** @typedef {import("./ResolverFactory").Plugin} Plugin */
/** @typedef {import("./ResolverFactory").UserResolveOptions} ResolveOptions */
/** @typedef {{
* (context: object, path: string, request: string, resolveContext: ResolveContext, callback: ResolveCallback): void;
* (context: object, path: string, request: string, callback: ResolveCallback): void;
* (path: string, request: string, resolveContext: ResolveContext, callback: ResolveCallback): void;
* (path: string, request: string, callback: ResolveCallback): void;
* }} ResolveFunctionAsync
*/
/** @typedef {{
* (context: object, path: string, request: string): string|false;
* (path: string, request: string): string|false;
* }} ResolveFunction
*/
const nodeFileSystem = new CachedInputFileSystem(fs, 4000);
const nodeContext = {
environments: ["node+es3+es5+process+native"]
};
const asyncResolver = ResolverFactory.createResolver({
conditionNames: ["node"],
extensions: [".js", ".json", ".node"],
fileSystem: nodeFileSystem
});
/**
* @type {ResolveFunctionAsync}
*/
const resolve =
/**
* @param {object|string} context
* @param {string} path
* @param {string|ResolveContext|ResolveCallback} request
* @param {ResolveContext|ResolveCallback=} resolveContext
* @param {ResolveCallback=} callback
*/
(context, path, request, resolveContext, callback) => {
if (typeof context === "string") {
callback = /** @type {ResolveCallback} */ (resolveContext);
resolveContext = /** @type {ResolveContext} */ (request);
request = path;
path = context;
context = nodeContext;
}
if (typeof callback !== "function") {
callback = /** @type {ResolveCallback} */ (resolveContext);
}
asyncResolver.resolve(
context,
path,
/** @type {string} */ (request),
/** @type {ResolveContext} */ (resolveContext),
/** @type {ResolveCallback} */ (callback)
);
};
const syncResolver = ResolverFactory.createResolver({
conditionNames: ["node"],
extensions: [".js", ".json", ".node"],
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
/**
* @type {ResolveFunction}
*/
const resolveSync =
/**
* @param {object|string} context
* @param {string} path
* @param {string=} request
*/
(context, path, request) => {
if (typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncResolver.resolveSync(
context,
path,
/** @type {string} */ (request)
);
};
/** @typedef {Omit<ResolveOptions, "fileSystem"> & Partial<Pick<ResolveOptions, "fileSystem">>} ResolveOptionsOptionalFS */
/**
* @param {ResolveOptionsOptionalFS} options Resolver options
* @returns {ResolveFunctionAsync} Resolver function
*/
function create(options) {
const resolver = ResolverFactory.createResolver({
fileSystem: nodeFileSystem,
...options
});
/**
* @param {object|string} context Custom context
* @param {string} path Base path
* @param {string|ResolveContext|ResolveCallback} request String to resolve
* @param {ResolveContext|ResolveCallback=} resolveContext Resolve context
* @param {ResolveCallback=} callback Result callback
*/
return function (context, path, request, resolveContext, callback) {
if (typeof context === "string") {
callback = /** @type {ResolveCallback} */ (resolveContext);
resolveContext = /** @type {ResolveContext} */ (request);
request = path;
path = context;
context = nodeContext;
}
if (typeof callback !== "function") {
callback = /** @type {ResolveCallback} */ (resolveContext);
}
resolver.resolve(
context,
path,
/** @type {string} */ (request),
/** @type {ResolveContext} */ (resolveContext),
callback
);
};
}
/**
* @param {ResolveOptionsOptionalFS} options Resolver options
* @returns {ResolveFunction} Resolver function
*/
function createSync(options) {
const resolver = ResolverFactory.createResolver({
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem,
...options
});
/**
* @param {object|string} context custom context
* @param {string} path base path
* @param {string=} request request to resolve
* @returns {string|false} Resolved path or false
*/
return function (context, path, request) {
if (typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return resolver.resolveSync(context, path, /** @type {string} */ (request));
};
}
/**
* @template A
* @template B
* @param {A} obj input a
* @param {B} exports input b
* @returns {A & B} merged
*/
const mergeExports = (obj, exports) => {
const descriptors = Object.getOwnPropertyDescriptors(exports);
Object.defineProperties(obj, descriptors);
return /** @type {A & B} */ (Object.freeze(obj));
};
module.exports = mergeExports(resolve, {
get sync() {
return resolveSync;
},
create: mergeExports(create, {
get sync() {
return createSync;
}
}),
ResolverFactory,
CachedInputFileSystem,
get CloneBasenamePlugin() {
return require("./CloneBasenamePlugin");
},
get LogInfoPlugin() {
return require("./LogInfoPlugin");
},
get forEachBail() {
return require("./forEachBail");
}
});

View File

@ -0,0 +1,573 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
/** @typedef {string|(string|ConditionalMapping)[]} DirectMapping */
/** @typedef {{[k: string]: MappingValue}} ConditionalMapping */
/** @typedef {ConditionalMapping|DirectMapping|null} MappingValue */
/** @typedef {Record<string, MappingValue>|ConditionalMapping|DirectMapping} ExportsField */
/** @typedef {Record<string, MappingValue>} ImportsField */
/**
* Processing exports/imports field
* @callback FieldProcessor
* @param {string} request request
* @param {Set<string>} conditionNames condition names
* @returns {[string[], string | null]} resolved paths with used field
*/
/*
Example exports field:
{
".": "./main.js",
"./feature": {
"browser": "./feature-browser.js",
"default": "./feature.js"
}
}
Terminology:
Enhanced-resolve name keys ("." and "./feature") as exports field keys.
If value is string or string[], mapping is called as a direct mapping
and value called as a direct export.
If value is key-value object, mapping is called as a conditional mapping
and value called as a conditional export.
Key in conditional mapping is called condition name.
Conditional mapping nested in another conditional mapping is called nested mapping.
----------
Example imports field:
{
"#a": "./main.js",
"#moment": {
"browser": "./moment/index.js",
"default": "moment"
},
"#moment/": {
"browser": "./moment/",
"default": "moment/"
}
}
Terminology:
Enhanced-resolve name keys ("#a" and "#moment/", "#moment") as imports field keys.
If value is string or string[], mapping is called as a direct mapping
and value called as a direct export.
If value is key-value object, mapping is called as a conditional mapping
and value called as a conditional export.
Key in conditional mapping is called condition name.
Conditional mapping nested in another conditional mapping is called nested mapping.
*/
const { parseIdentifier } = require("./identifier");
const slashCode = "/".charCodeAt(0);
const dotCode = ".".charCodeAt(0);
const hashCode = "#".charCodeAt(0);
const patternRegEx = /\*/g;
/**
* @param {ExportsField} exportsField the exports field
* @returns {FieldProcessor} process callback
*/
module.exports.processExportsField = function processExportsField(
exportsField
) {
return createFieldProcessor(
buildExportsField(exportsField),
request => (request.length === 0 ? "." : "./" + request),
assertExportsFieldRequest,
assertExportTarget
);
};
/**
* @param {ImportsField} importsField the exports field
* @returns {FieldProcessor} process callback
*/
module.exports.processImportsField = function processImportsField(
importsField
) {
return createFieldProcessor(
importsField,
request => "#" + request,
assertImportsFieldRequest,
assertImportTarget
);
};
/**
* @param {ExportsField | ImportsField} field root
* @param {(s: string) => string} normalizeRequest Normalize request, for `imports` field it adds `#`, for `exports` field it adds `.` or `./`
* @param {(s: string) => string} assertRequest assertRequest
* @param {(s: string, f: boolean) => void} assertTarget assertTarget
* @returns {FieldProcessor} field processor
*/
function createFieldProcessor(
field,
normalizeRequest,
assertRequest,
assertTarget
) {
return function fieldProcessor(request, conditionNames) {
request = assertRequest(request);
const match = findMatch(normalizeRequest(request), field);
if (match === null) return [[], null];
const [mapping, remainingRequest, isSubpathMapping, isPattern, usedField] =
match;
/** @type {DirectMapping|null} */
let direct = null;
if (isConditionalMapping(mapping)) {
direct = conditionalMapping(
/** @type {ConditionalMapping} */ (mapping),
conditionNames
);
// matching not found
if (direct === null) return [[], null];
} else {
direct = /** @type {DirectMapping} */ (mapping);
}
return [
directMapping(
remainingRequest,
isPattern,
isSubpathMapping,
direct,
conditionNames,
assertTarget
),
usedField
];
};
}
/**
* @param {string} request request
* @returns {string} updated request
*/
function assertExportsFieldRequest(request) {
if (request.charCodeAt(0) !== dotCode) {
throw new Error('Request should be relative path and start with "."');
}
if (request.length === 1) return "";
if (request.charCodeAt(1) !== slashCode) {
throw new Error('Request should be relative path and start with "./"');
}
if (request.charCodeAt(request.length - 1) === slashCode) {
throw new Error("Only requesting file allowed");
}
return request.slice(2);
}
/**
* @param {string} request request
* @returns {string} updated request
*/
function assertImportsFieldRequest(request) {
if (request.charCodeAt(0) !== hashCode) {
throw new Error('Request should start with "#"');
}
if (request.length === 1) {
throw new Error("Request should have at least 2 characters");
}
if (request.charCodeAt(1) === slashCode) {
throw new Error('Request should not start with "#/"');
}
if (request.charCodeAt(request.length - 1) === slashCode) {
throw new Error("Only requesting file allowed");
}
return request.slice(1);
}
/**
* @param {string} exp export target
* @param {boolean} expectFolder is folder expected
*/
function assertExportTarget(exp, expectFolder) {
const parsedIdentifier = parseIdentifier(exp);
if (!parsedIdentifier) {
return;
}
const [relativePath] = parsedIdentifier;
const isFolder =
relativePath.charCodeAt(relativePath.length - 1) === slashCode;
if (isFolder !== expectFolder) {
throw new Error(
expectFolder
? `Expecting folder to folder mapping. ${JSON.stringify(
exp
)} should end with "/"`
: `Expecting file to file mapping. ${JSON.stringify(
exp
)} should not end with "/"`
);
}
}
/**
* @param {string} imp import target
* @param {boolean} expectFolder is folder expected
*/
function assertImportTarget(imp, expectFolder) {
const parsedIdentifier = parseIdentifier(imp);
if (!parsedIdentifier) {
return;
}
const [relativePath] = parsedIdentifier;
const isFolder =
relativePath.charCodeAt(relativePath.length - 1) === slashCode;
if (isFolder !== expectFolder) {
throw new Error(
expectFolder
? `Expecting folder to folder mapping. ${JSON.stringify(
imp
)} should end with "/"`
: `Expecting file to file mapping. ${JSON.stringify(
imp
)} should not end with "/"`
);
}
}
/**
* @param {string} a first string
* @param {string} b second string
* @returns {number} compare result
*/
function patternKeyCompare(a, b) {
const aPatternIndex = a.indexOf("*");
const bPatternIndex = b.indexOf("*");
const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1;
const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1;
if (baseLenA > baseLenB) return -1;
if (baseLenB > baseLenA) return 1;
if (aPatternIndex === -1) return 1;
if (bPatternIndex === -1) return -1;
if (a.length > b.length) return -1;
if (b.length > a.length) return 1;
return 0;
}
/**
* Trying to match request to field
* @param {string} request request
* @param {ExportsField | ImportsField} field exports or import field
* @returns {[MappingValue, string, boolean, boolean, string]|null} match or null, number is negative and one less when it's a folder mapping, number is request.length + 1 for direct mappings
*/
function findMatch(request, field) {
if (
Object.prototype.hasOwnProperty.call(field, request) &&
!request.includes("*") &&
!request.endsWith("/")
) {
const target = /** @type {{[k: string]: MappingValue}} */ (field)[request];
return [target, "", false, false, request];
}
/** @type {string} */
let bestMatch = "";
/** @type {string|undefined} */
let bestMatchSubpath;
const keys = Object.getOwnPropertyNames(field);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const patternIndex = key.indexOf("*");
if (patternIndex !== -1 && request.startsWith(key.slice(0, patternIndex))) {
const patternTrailer = key.slice(patternIndex + 1);
if (
request.length >= key.length &&
request.endsWith(patternTrailer) &&
patternKeyCompare(bestMatch, key) === 1 &&
key.lastIndexOf("*") === patternIndex
) {
bestMatch = key;
bestMatchSubpath = request.slice(
patternIndex,
request.length - patternTrailer.length
);
}
}
// For legacy `./foo/`
else if (
key[key.length - 1] === "/" &&
request.startsWith(key) &&
patternKeyCompare(bestMatch, key) === 1
) {
bestMatch = key;
bestMatchSubpath = request.slice(key.length);
}
}
if (bestMatch === "") return null;
const target = /** @type {{[k: string]: MappingValue}} */ (field)[bestMatch];
const isSubpathMapping = bestMatch.endsWith("/");
const isPattern = bestMatch.includes("*");
return [
target,
/** @type {string} */ (bestMatchSubpath),
isSubpathMapping,
isPattern,
bestMatch
];
}
/**
* @param {ConditionalMapping|DirectMapping|null} mapping mapping
* @returns {boolean} is conditional mapping
*/
function isConditionalMapping(mapping) {
return (
mapping !== null && typeof mapping === "object" && !Array.isArray(mapping)
);
}
/**
* @param {string|undefined} remainingRequest remaining request when folder mapping, undefined for file mappings
* @param {boolean} isPattern true, if mapping is a pattern (contains "*")
* @param {boolean} isSubpathMapping true, for subpath mappings
* @param {DirectMapping|null} mappingTarget direct export
* @param {Set<string>} conditionNames condition names
* @param {(d: string, f: boolean) => void} assert asserting direct value
* @returns {string[]} mapping result
*/
function directMapping(
remainingRequest,
isPattern,
isSubpathMapping,
mappingTarget,
conditionNames,
assert
) {
if (mappingTarget === null) return [];
if (typeof mappingTarget === "string") {
return [
targetMapping(
remainingRequest,
isPattern,
isSubpathMapping,
mappingTarget,
assert
)
];
}
/** @type {string[]} */
const targets = [];
for (const exp of mappingTarget) {
if (typeof exp === "string") {
targets.push(
targetMapping(
remainingRequest,
isPattern,
isSubpathMapping,
exp,
assert
)
);
continue;
}
const mapping = conditionalMapping(exp, conditionNames);
if (!mapping) continue;
const innerExports = directMapping(
remainingRequest,
isPattern,
isSubpathMapping,
mapping,
conditionNames,
assert
);
for (const innerExport of innerExports) {
targets.push(innerExport);
}
}
return targets;
}
/**
* @param {string|undefined} remainingRequest remaining request when folder mapping, undefined for file mappings
* @param {boolean} isPattern true, if mapping is a pattern (contains "*")
* @param {boolean} isSubpathMapping true, for subpath mappings
* @param {string} mappingTarget direct export
* @param {(d: string, f: boolean) => void} assert asserting direct value
* @returns {string} mapping result
*/
function targetMapping(
remainingRequest,
isPattern,
isSubpathMapping,
mappingTarget,
assert
) {
if (remainingRequest === undefined) {
assert(mappingTarget, false);
return mappingTarget;
}
if (isSubpathMapping) {
assert(mappingTarget, true);
return mappingTarget + remainingRequest;
}
assert(mappingTarget, false);
let result = mappingTarget;
if (isPattern) {
result = result.replace(
patternRegEx,
remainingRequest.replace(/\$/g, "$$")
);
}
return result;
}
/**
* @param {ConditionalMapping} conditionalMapping_ conditional mapping
* @param {Set<string>} conditionNames condition names
* @returns {DirectMapping|null} direct mapping if found
*/
function conditionalMapping(conditionalMapping_, conditionNames) {
/** @type {[ConditionalMapping, string[], number][]} */
let lookup = [[conditionalMapping_, Object.keys(conditionalMapping_), 0]];
loop: while (lookup.length > 0) {
const [mapping, conditions, j] = lookup[lookup.length - 1];
for (let i = j; i < conditions.length; i++) {
const condition = conditions[i];
if (condition === "default") {
const innerMapping = mapping[condition];
// is nested
if (isConditionalMapping(innerMapping)) {
const conditionalMapping = /** @type {ConditionalMapping} */ (
innerMapping
);
lookup[lookup.length - 1][2] = i + 1;
lookup.push([conditionalMapping, Object.keys(conditionalMapping), 0]);
continue loop;
}
return /** @type {DirectMapping} */ (innerMapping);
}
if (conditionNames.has(condition)) {
const innerMapping = mapping[condition];
// is nested
if (isConditionalMapping(innerMapping)) {
const conditionalMapping = /** @type {ConditionalMapping} */ (
innerMapping
);
lookup[lookup.length - 1][2] = i + 1;
lookup.push([conditionalMapping, Object.keys(conditionalMapping), 0]);
continue loop;
}
return /** @type {DirectMapping} */ (innerMapping);
}
}
lookup.pop();
}
return null;
}
/**
* @param {ExportsField} field exports field
* @returns {ExportsField} normalized exports field
*/
function buildExportsField(field) {
// handle syntax sugar, if exports field is direct mapping for "."
if (typeof field === "string" || Array.isArray(field)) {
return { ".": field };
}
const keys = Object.keys(field);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key.charCodeAt(0) !== dotCode) {
// handle syntax sugar, if exports field is conditional mapping for "."
if (i === 0) {
while (i < keys.length) {
const charCode = keys[i].charCodeAt(0);
if (charCode === dotCode || charCode === slashCode) {
throw new Error(
`Exports field key should be relative path and start with "." (key: ${JSON.stringify(
key
)})`
);
}
i++;
}
return { ".": field };
}
throw new Error(
`Exports field key should be relative path and start with "." (key: ${JSON.stringify(
key
)})`
);
}
if (key.length === 1) {
continue;
}
if (key.charCodeAt(1) !== slashCode) {
throw new Error(
`Exports field key should be relative path and start with "./" (key: ${JSON.stringify(
key
)})`
);
}
}
return field;
}

View File

@ -0,0 +1,69 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const PATH_QUERY_FRAGMENT_REGEXP =
/^(#?(?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
const ZERO_ESCAPE_REGEXP = /\0(.)/g;
/**
* @param {string} identifier identifier
* @returns {[string, string, string]|null} parsed identifier
*/
function parseIdentifier(identifier) {
if (!identifier) {
return null;
}
const firstEscape = identifier.indexOf("\0");
if (firstEscape < 0) {
// Fast path for inputs that don't use \0 escaping.
const queryStart = identifier.indexOf("?");
// Start at index 1 to ignore a possible leading hash.
const fragmentStart = identifier.indexOf("#", 1);
if (fragmentStart < 0) {
if (queryStart < 0) {
// No fragment, no query
return [identifier, "", ""];
}
// Query, no fragment
return [
identifier.slice(0, queryStart),
identifier.slice(queryStart),
""
];
}
if (queryStart < 0 || fragmentStart < queryStart) {
// Fragment, no query
return [
identifier.slice(0, fragmentStart),
"",
identifier.slice(fragmentStart)
];
}
// Query and fragment
return [
identifier.slice(0, queryStart),
identifier.slice(queryStart, fragmentStart),
identifier.slice(fragmentStart)
];
}
const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
if (!match) return null;
return [
match[1].replace(ZERO_ESCAPE_REGEXP, "$1"),
match[2] ? match[2].replace(ZERO_ESCAPE_REGEXP, "$1") : "",
match[3] || ""
];
}
module.exports.parseIdentifier = parseIdentifier;

View File

@ -0,0 +1,8 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = {};

203
app_vue/node_modules/enhanced-resolve/lib/util/path.js generated vendored Normal file
View File

@ -0,0 +1,203 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
const CHAR_HASH = "#".charCodeAt(0);
const CHAR_SLASH = "/".charCodeAt(0);
const CHAR_BACKSLASH = "\\".charCodeAt(0);
const CHAR_A = "A".charCodeAt(0);
const CHAR_Z = "Z".charCodeAt(0);
const CHAR_LOWER_A = "a".charCodeAt(0);
const CHAR_LOWER_Z = "z".charCodeAt(0);
const CHAR_DOT = ".".charCodeAt(0);
const CHAR_COLON = ":".charCodeAt(0);
const posixNormalize = path.posix.normalize;
const winNormalize = path.win32.normalize;
/**
* @enum {number}
*/
const PathType = Object.freeze({
Empty: 0,
Normal: 1,
Relative: 2,
AbsoluteWin: 3,
AbsolutePosix: 4,
Internal: 5
});
exports.PathType = PathType;
const invalidSegmentRegEx =
/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))?(\\|\/|$)/i;
exports.invalidSegmentRegEx = invalidSegmentRegEx;
const deprecatedInvalidSegmentRegEx =
/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i;
exports.deprecatedInvalidSegmentRegEx = deprecatedInvalidSegmentRegEx;
/**
* @param {string} p a path
* @returns {PathType} type of path
*/
const getType = p => {
switch (p.length) {
case 0:
return PathType.Empty;
case 1: {
const c0 = p.charCodeAt(0);
switch (c0) {
case CHAR_DOT:
return PathType.Relative;
case CHAR_SLASH:
return PathType.AbsolutePosix;
case CHAR_HASH:
return PathType.Internal;
}
return PathType.Normal;
}
case 2: {
const c0 = p.charCodeAt(0);
switch (c0) {
case CHAR_DOT: {
const c1 = p.charCodeAt(1);
switch (c1) {
case CHAR_DOT:
case CHAR_SLASH:
return PathType.Relative;
}
return PathType.Normal;
}
case CHAR_SLASH:
return PathType.AbsolutePosix;
case CHAR_HASH:
return PathType.Internal;
}
const c1 = p.charCodeAt(1);
if (c1 === CHAR_COLON) {
if (
(c0 >= CHAR_A && c0 <= CHAR_Z) ||
(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z)
) {
return PathType.AbsoluteWin;
}
}
return PathType.Normal;
}
}
const c0 = p.charCodeAt(0);
switch (c0) {
case CHAR_DOT: {
const c1 = p.charCodeAt(1);
switch (c1) {
case CHAR_SLASH:
return PathType.Relative;
case CHAR_DOT: {
const c2 = p.charCodeAt(2);
if (c2 === CHAR_SLASH) return PathType.Relative;
return PathType.Normal;
}
}
return PathType.Normal;
}
case CHAR_SLASH:
return PathType.AbsolutePosix;
case CHAR_HASH:
return PathType.Internal;
}
const c1 = p.charCodeAt(1);
if (c1 === CHAR_COLON) {
const c2 = p.charCodeAt(2);
if (
(c2 === CHAR_BACKSLASH || c2 === CHAR_SLASH) &&
((c0 >= CHAR_A && c0 <= CHAR_Z) ||
(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z))
) {
return PathType.AbsoluteWin;
}
}
return PathType.Normal;
};
exports.getType = getType;
/**
* @param {string} p a path
* @returns {string} the normalized path
*/
const normalize = p => {
switch (getType(p)) {
case PathType.Empty:
return p;
case PathType.AbsoluteWin:
return winNormalize(p);
case PathType.Relative: {
const r = posixNormalize(p);
return getType(r) === PathType.Relative ? r : `./${r}`;
}
}
return posixNormalize(p);
};
exports.normalize = normalize;
/**
* @param {string} rootPath the root path
* @param {string | undefined} request the request path
* @returns {string} the joined path
*/
const join = (rootPath, request) => {
if (!request) return normalize(rootPath);
const requestType = getType(request);
switch (requestType) {
case PathType.AbsolutePosix:
return posixNormalize(request);
case PathType.AbsoluteWin:
return winNormalize(request);
}
switch (getType(rootPath)) {
case PathType.Normal:
case PathType.Relative:
case PathType.AbsolutePosix:
return posixNormalize(`${rootPath}/${request}`);
case PathType.AbsoluteWin:
return winNormalize(`${rootPath}\\${request}`);
}
switch (requestType) {
case PathType.Empty:
return rootPath;
case PathType.Relative: {
const r = posixNormalize(rootPath);
return getType(r) === PathType.Relative ? r : `./${r}`;
}
}
return posixNormalize(rootPath);
};
exports.join = join;
/** @type {Map<string, Map<string, string | undefined>>} */
const joinCache = new Map();
/**
* @param {string} rootPath the root path
* @param {string} request the request path
* @returns {string} the joined path
*/
const cachedJoin = (rootPath, request) => {
/** @type {string | undefined} */
let cacheEntry;
let cache = joinCache.get(rootPath);
if (cache === undefined) {
joinCache.set(rootPath, (cache = new Map()));
} else {
cacheEntry = cache.get(request);
if (cacheEntry !== undefined) return cacheEntry;
}
cacheEntry = join(rootPath, request);
cache.set(request, cacheEntry);
return cacheEntry;
};
exports.cachedJoin = cachedJoin;

View File

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = {
/**
* @type {Record<string, string>}
*/
versions: {},
/**
* @param {function} fn function
*/
nextTick(fn) {
const args = Array.prototype.slice.call(arguments, 1);
Promise.resolve().then(function () {
fn.apply(null, args);
});
}
};

72
app_vue/node_modules/enhanced-resolve/package.json generated vendored Normal file
View File

@ -0,0 +1,72 @@
{
"name": "enhanced-resolve",
"version": "5.18.1",
"author": "Tobias Koppers @sokra",
"description": "Offers a async require.resolve function. It's highly configurable.",
"files": [
"lib",
"types.d.ts",
"LICENSE"
],
"browser": {
"process": "./lib/util/process-browser.js",
"module": "./lib/util/module-browser.js"
},
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
},
"license": "MIT",
"devDependencies": {
"@types/graceful-fs": "^4.1.6",
"@types/jest": "^27.5.1",
"@types/node": "20.9.5",
"cspell": "4.2.8",
"eslint": "^7.9.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jsdoc": "^30.5.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4",
"husky": "^6.0.0",
"jest": "^27.5.1",
"lint-staged": "^10.4.0",
"memfs": "^3.2.0",
"prettier": "^2.1.2",
"tooling": "webpack/tooling#v1.23.1",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=10.13.0"
},
"main": "lib/index.js",
"types": "types.d.ts",
"homepage": "http://github.com/webpack/enhanced-resolve",
"scripts": {
"lint": "yarn run code-lint && yarn run type-lint && yarn typings-test && yarn run special-lint && yarn run spelling",
"fix": "yarn run code-lint-fix && yarn run special-lint-fix",
"code-lint": "eslint --cache lib test",
"code-lint-fix": "eslint --cache lib test --fix",
"type-lint": "tsc",
"typings-test": "tsc -p tsconfig.types.test.json",
"type-report": "rimraf coverage && yarn cover:types && yarn cover:report && open-cli coverage/lcov-report/index.html",
"special-lint": "node node_modules/tooling/lockfile-lint && node node_modules/tooling/inherit-types && node node_modules/tooling/format-file-header && node node_modules/tooling/generate-types",
"special-lint-fix": "node node_modules/tooling/inherit-types --write && node node_modules/tooling/format-file-header --write && node node_modules/tooling/generate-types --write",
"pretty": "prettier --loglevel warn --write \"lib/**/*.{js,json}\" \"test/*.js\"",
"pretest": "yarn lint",
"spelling": "cspell \"**\"",
"test:only": "node_modules/.bin/jest",
"test:watch": "yarn test:only -- --watch",
"test:coverage": "yarn test:only -- --collectCoverageFrom=\"lib/**/*.js\" --coverage",
"test": "yarn test:coverage",
"precover": "yarn lint",
"prepare": "husky install"
},
"lint-staged": {
"*": "cspell --no-must-find-files",
"*.js": "eslint --cache"
},
"repository": {
"type": "git",
"url": "git://github.com/webpack/enhanced-resolve.git"
}
}

1135
app_vue/node_modules/enhanced-resolve/types.d.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff