feat: refactoring project

This commit is contained in:
Carlos
2024-11-23 14:56:07 -05:00
parent f0c2a50c18
commit 1c6db5818d
2351 changed files with 39323 additions and 60326 deletions

View File

@@ -13,7 +13,7 @@
* @returns {boolean} returns true if all the elements of passed arrays are strictly equal.
*/
exports.equals = (a, b) => {
module.exports.equals = (a, b) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
@@ -28,8 +28,13 @@ exports.equals = (a, b) => {
* @param {(value: T) => boolean} fn Partition function which partitions based on truthiness of result.
* @returns {[Array<T>, Array<T>]} returns the values of `arr` partitioned into two new arrays based on fn predicate.
*/
exports.groupBy = (arr = [], fn) => {
return arr.reduce(
module.exports.groupBy = (
// eslint-disable-next-line default-param-last
arr = [],
fn
) =>
arr.reduce(
/**
* @param {[Array<T>, Array<T>]} groups An accumulator storing already partitioned values returned from previous call.
* @param {T} value The value of the current element
@@ -41,4 +46,3 @@ exports.groupBy = (arr = [], fn) => {
},
[[], []]
);
};

View File

@@ -56,7 +56,7 @@ class ArrayQueue {
*/
dequeue() {
if (this._listReversed.length === 0) {
if (this._list.length === 0) return undefined;
if (this._list.length === 0) return;
if (this._list.length === 1) return this._list.pop();
if (this._list.length < 16) return this._list.shift();
const temp = this._listReversed;

View File

@@ -20,7 +20,7 @@ let inHandleResult = 0;
* @template T
* @callback Callback
* @param {(WebpackError | null)=} err
* @param {T=} result
* @param {(T | null)=} result
*/
/**
@@ -37,15 +37,27 @@ class AsyncQueueEntry {
this.item = item;
/** @type {typeof QUEUED_STATE | typeof PROCESSING_STATE | typeof DONE_STATE} */
this.state = QUEUED_STATE;
/** @type {Callback<R> | undefined} */
this.callback = callback;
/** @type {Callback<R>[] | undefined} */
this.callbacks = undefined;
/** @type {R | null | undefined} */
this.result = undefined;
/** @type {WebpackError | undefined} */
/** @type {WebpackError | null | undefined} */
this.error = undefined;
}
}
/**
* @template T, K
* @typedef {function(T): K} getKey
*/
/**
* @template T, R
* @typedef {function(T, Callback<R>): void} Processor
*/
/**
* @template T
* @template K
@@ -56,16 +68,19 @@ class AsyncQueue {
* @param {object} options options object
* @param {string=} options.name name of the queue
* @param {number=} options.parallelism how many items should be processed at once
* @param {string=} options.context context of execution
* @param {AsyncQueue<any, any, any>=} options.parent parent queue, which will have priority over this queue and with shared parallelism
* @param {function(T): K=} options.getKey extract key from item
* @param {function(T, Callback<R>): void} options.processor async function to process items
* @param {getKey<T, K>=} options.getKey extract key from item
* @param {Processor<T, R>} options.processor async function to process items
*/
constructor({ name, parallelism, parent, processor, getKey }) {
constructor({ name, context, parallelism, parent, processor, getKey }) {
this._name = name;
this._context = context || "normal";
this._parallelism = parallelism || 1;
this._processor = processor;
this._getKey =
getKey || /** @type {(T) => K} */ (item => /** @type {any} */ (item));
getKey ||
/** @type {getKey<T, K>} */ (item => /** @type {T & K} */ (item));
/** @type {Map<K, AsyncQueueEntry<T, K, R>>} */
this._entries = new Map();
/** @type {ArrayQueue<AsyncQueueEntry<T, K, R>>} */
@@ -76,6 +91,7 @@ class AsyncQueue {
this._willEnsureProcessing = false;
this._needProcessing = false;
this._stopped = false;
/** @type {AsyncQueue<any, any, any>} */
this._root = parent ? parent._root : this;
if (parent) {
if (this._root._children === undefined) {
@@ -94,13 +110,27 @@ class AsyncQueue {
beforeStart: new AsyncSeriesHook(["item"]),
/** @type {SyncHook<[T]>} */
started: new SyncHook(["item"]),
/** @type {SyncHook<[T, Error, R]>} */
/** @type {SyncHook<[T, WebpackError | null | undefined, R | null | undefined]>} */
result: new SyncHook(["item", "error", "result"])
};
this._ensureProcessing = this._ensureProcessing.bind(this);
}
/**
* @returns {string} context of execution
*/
getContext() {
return this._context;
}
/**
* @param {string} value context of execution
*/
setContext(value) {
this._context = value;
}
/**
* @param {T} item an item
* @param {Callback<R>} callback callback function
@@ -202,9 +232,14 @@ class AsyncQueue {
this._queued = new ArrayQueue();
const root = this._root;
for (const entry of queue) {
this._entries.delete(this._getKey(entry.item));
this._entries.delete(
this._getKey(/** @type {AsyncQueueEntry<T, K, R>} */ (entry).item)
);
root._activeTasks++;
this._handleResult(entry, new WebpackError("Queue was stopped"));
this._handleResult(
/** @type {AsyncQueueEntry<T, K, R>} */ (entry),
new WebpackError("Queue was stopped")
);
}
}
@@ -308,7 +343,7 @@ class AsyncQueue {
});
} catch (err) {
if (inCallback) throw err;
this._handleResult(entry, err, null);
this._handleResult(entry, /** @type {WebpackError} */ (err), null);
}
this.hooks.started.call(entry.item);
});
@@ -316,8 +351,8 @@ class AsyncQueue {
/**
* @param {AsyncQueueEntry<T, K, R>} entry the entry
* @param {WebpackError=} err error, if any
* @param {R=} result result, if any
* @param {(WebpackError | null)=} err error, if any
* @param {(R | null)=} result result, if any
* @returns {void}
*/
_handleResult(entry, err, result) {
@@ -326,7 +361,7 @@ class AsyncQueue {
? makeWebpackError(hookError, `AsyncQueue(${this._name}).hooks.result`)
: err;
const callback = entry.callback;
const callback = /** @type {Callback<R>} */ (entry.callback);
const callbacks = entry.callbacks;
entry.state = DONE_STATE;
entry.callback = undefined;

View File

@@ -19,7 +19,7 @@ const last = set => {
/**
* @template T
* @param {Iterable<T>} iterable iterable
* @param {function(T): boolean} filter predicate
* @param {function(T): boolean | null | undefined} filter predicate
* @returns {boolean} true, if some items match the filter predicate
*/
const someInIterable = (iterable, filter) => {
@@ -36,11 +36,10 @@ const someInIterable = (iterable, filter) => {
*/
const countIterable = iterable => {
let i = 0;
// eslint-disable-next-line no-unused-vars
for (const _ of iterable) i++;
return i;
};
exports.last = last;
exports.someInIterable = someInIterable;
exports.countIterable = countIterable;
module.exports.last = last;
module.exports.someInIterable = someInIterable;
module.exports.countIterable = countIterable;

View File

@@ -8,6 +8,16 @@
const { first } = require("./SetHelpers");
const SortableSet = require("./SortableSet");
/**
* @template T
* @typedef {LazyBucketSortedSet<T, any> | SortableSet<T>} Entry
*/
/**
* @template T
* @typedef {(function(T): any) | (function(any, any): number)} Arg
*/
/**
* Multi layer bucket sorted set:
* Supports adding non-existing items (DO NOT ADD ITEM TWICE),
@@ -24,14 +34,15 @@ class LazyBucketSortedSet {
/**
* @param {function(T): K} getKey function to get key from item
* @param {function(K, K): number} comparator comparator to sort keys
* @param {...((function(T): any) | (function(any, any): number))} args more pairs of getKey and comparator plus optional final comparator for the last layer
* @param {...Arg<T>} args more pairs of getKey and comparator plus optional final comparator for the last layer
*/
constructor(getKey, comparator, ...args) {
this._getKey = getKey;
/** @type {Arg<T>[]} */
this._innerArgs = args;
this._leaf = args.length <= 1;
this._keys = new SortableSet(undefined, comparator);
/** @type {Map<K, LazyBucketSortedSet<T, any> | SortableSet<T>>} */
/** @type {Map<K, Entry<T>>} */
this._map = new Map();
this._unsortedItems = new Set();
this.size = 0;
@@ -54,13 +65,18 @@ class LazyBucketSortedSet {
_addInternal(key, item) {
let entry = this._map.get(key);
if (entry === undefined) {
entry = this._leaf
? new SortableSet(undefined, this._innerArgs[0])
: new /** @type {any} */ (LazyBucketSortedSet)(...this._innerArgs);
entry =
/** @type {Entry<T>} */
(
this._leaf
? new SortableSet(undefined, this._innerArgs[0])
: new /** @type {TODO} */ (LazyBucketSortedSet)(...this._innerArgs)
);
this._keys.add(key);
this._map.set(key, entry);
}
entry.add(item);
/** @type {Entry<T>} */
(entry).add(item);
}
/**
@@ -74,7 +90,7 @@ class LazyBucketSortedSet {
return;
}
const key = this._getKey(item);
const entry = this._map.get(key);
const entry = /** @type {Entry<T>} */ (this._map.get(key));
entry.delete(item);
if (entry.size === 0) {
this._deleteKey(key);
@@ -94,7 +110,7 @@ class LazyBucketSortedSet {
* @returns {T | undefined} an item
*/
popFirst() {
if (this.size === 0) return undefined;
if (this.size === 0) return;
this.size--;
if (this._unsortedItems.size > 0) {
for (const item of this._unsortedItems) {
@@ -104,25 +120,24 @@ class LazyBucketSortedSet {
this._unsortedItems.clear();
}
this._keys.sort();
const key = first(this._keys);
const key = /** @type {K} */ (first(this._keys));
const entry = this._map.get(key);
if (this._leaf) {
const leafEntry = /** @type {SortableSet<T>} */ (entry);
leafEntry.sort();
const item = first(leafEntry);
const item = /** @type {T} */ (first(leafEntry));
leafEntry.delete(item);
if (leafEntry.size === 0) {
this._deleteKey(key);
}
return item;
} else {
const nodeEntry = /** @type {LazyBucketSortedSet<T, any>} */ (entry);
const item = nodeEntry.popFirst();
if (nodeEntry.size === 0) {
this._deleteKey(key);
}
return item;
}
const nodeEntry = /** @type {LazyBucketSortedSet<T, any>} */ (entry);
const item = nodeEntry.popFirst();
if (nodeEntry.size === 0) {
this._deleteKey(key);
}
return item;
}
/**
@@ -135,7 +150,6 @@ class LazyBucketSortedSet {
if (remove) {
this._unsortedItems.delete(item);
this.size--;
return;
}
};
}
@@ -163,32 +177,31 @@ class LazyBucketSortedSet {
this._addInternal(newKey, item);
}
};
} else {
const oldEntry = /** @type {LazyBucketSortedSet<T, any>} */ (
this._map.get(key)
);
const finishUpdate = oldEntry.startUpdate(item);
return remove => {
if (remove) {
this.size--;
finishUpdate(true);
if (oldEntry.size === 0) {
this._deleteKey(key);
}
return;
}
const newKey = this._getKey(item);
if (key === newKey) {
finishUpdate();
} else {
finishUpdate(true);
if (oldEntry.size === 0) {
this._deleteKey(key);
}
this._addInternal(newKey, item);
}
};
}
const oldEntry = /** @type {LazyBucketSortedSet<T, any>} */ (
this._map.get(key)
);
const finishUpdate = oldEntry.startUpdate(item);
return remove => {
if (remove) {
this.size--;
finishUpdate(true);
if (oldEntry.size === 0) {
this._deleteKey(key);
}
return;
}
const newKey = this._getKey(item);
if (key === newKey) {
finishUpdate();
} else {
finishUpdate(true);
if (oldEntry.size === 0) {
this._deleteKey(key);
}
this._addInternal(newKey, item);
}
};
}
/**
@@ -215,16 +228,19 @@ class LazyBucketSortedSet {
* @returns {Iterator<T>} the iterator
*/
[Symbol.iterator]() {
/** @type {Iterator<T>[]} */
const iterators = [];
this._appendIterators(iterators);
iterators.reverse();
let currentIterator = iterators.pop();
let currentIterator =
/** @type {Iterator<T>} */
(iterators.pop());
return {
next: () => {
const res = currentIterator.next();
if (res.done) {
if (iterators.length === 0) return res;
currentIterator = iterators.pop();
currentIterator = /** @type {Iterator<T>} */ (iterators.pop());
return currentIterator.next();
}
return res;

View File

@@ -138,6 +138,9 @@ class LazySet {
return this._set.delete(value);
}
/**
* @returns {IterableIterator<[T, T]>} entries
*/
entries() {
this._deopt = true;
if (this._needMerge) this._merge();
@@ -152,6 +155,7 @@ class LazySet {
forEach(callbackFn, thisArg) {
this._deopt = true;
if (this._needMerge) this._merge();
// eslint-disable-next-line unicorn/no-array-for-each
this._set.forEach(callbackFn, thisArg);
}
@@ -164,18 +168,27 @@ class LazySet {
return this._set.has(item);
}
/**
* @returns {IterableIterator<T>} keys
*/
keys() {
this._deopt = true;
if (this._needMerge) this._merge();
return this._set.keys();
}
/**
* @returns {IterableIterator<T>} values
*/
values() {
this._deopt = true;
if (this._needMerge) this._merge();
return this._set.values();
}
/**
* @returns {IterableIterator<T>} iterable iterator
*/
[Symbol.iterator]() {
this._deopt = true;
if (this._needMerge) this._merge();

View File

@@ -9,14 +9,12 @@
* getOrInsert is a helper function for maps that allows you to get a value
* from a map if it exists, or insert a new value if it doesn't. If it value doesn't
* exist, it will be computed by the provided function.
*
* @template K
* @template V
* @param {Map<K, V>} map The map object to check
* @param {K} key The key to check
* @param {function(): V} computer function which will compute the value if it doesn't exist
* @returns {V} The value from the map, or the computed value
*
* @example
* ```js
* const map = new Map();
@@ -24,7 +22,7 @@
* console.log(value); // "value"
* ```
*/
exports.getOrInsert = (map, key, computer) => {
module.exports.getOrInsert = (map, key, computer) => {
// Grab key from map
const value = map.get(key);
// If the value already exists, return it

View File

@@ -5,7 +5,7 @@
"use strict";
const binarySearchBounds = require("../util/binarySearchBounds");
const binarySearchBounds = require("./binarySearchBounds");
/** @typedef {function(number): void} Callback */

View File

@@ -48,7 +48,7 @@ class Queue {
*/
dequeue() {
const result = this._iterator.next();
if (result.done) return undefined;
if (result.done) return;
this._set.delete(result.value);
return result.value;
}

View File

@@ -8,7 +8,6 @@
class Semaphore {
/**
* Creates an instance of Semaphore.
*
* @param {number} available the amount available number of "tasks"
* in the Semaphore
*/
@@ -41,12 +40,10 @@ class Semaphore {
}
_continue() {
if (this.available > 0) {
if (this.waiters.length > 0) {
this.available--;
const callback = /** @type {(function(): void)} */ (this.waiters.pop());
callback();
}
if (this.available > 0 && this.waiters.length > 0) {
this.available--;
const callback = /** @type {(function(): void)} */ (this.waiters.pop());
callback();
}
}
}

View File

@@ -65,7 +65,7 @@ const find = (set, fn) => {
/**
* @template T
* @param {Set<T>} set a set
* @param {Set<T> | ReadonlySet<T>} set a set
* @returns {T | undefined} first item
*/
const first = set => {
@@ -87,8 +87,8 @@ const combine = (a, b) => {
return set;
};
exports.intersect = intersect;
exports.isSubset = isSubset;
exports.find = find;
exports.first = first;
exports.combine = combine;
module.exports.intersect = intersect;
module.exports.isSubset = isSubset;
module.exports.find = find;
module.exports.first = first;
module.exports.combine = combine;

View File

@@ -15,15 +15,16 @@ const NONE = Symbol("not sorted");
class SortableSet extends Set {
/**
* Create a new sortable set
* @template T
* @param {Iterable<T>=} initialIterable The initial iterable value
* @typedef {function(T, T): number} SortFunction
* @param {SortFunction=} defaultSort Default sorting function
* @param {SortFunction<T>=} defaultSort Default sorting function
*/
constructor(initialIterable, defaultSort) {
super(initialIterable);
/**
* @private
* @type {undefined | function(T, T): number}}
* @type {undefined | SortFunction<T>}
*/
this._sortFn = defaultSort;
/**
@@ -76,7 +77,7 @@ class SortableSet extends Set {
/**
* Sort with a comparer function
* @param {SortFunction} sortFn Sorting comparer function
* @param {SortFunction<T> | undefined} sortFn Sorting comparer function
* @returns {void}
*/
sortWith(sortFn) {

View File

@@ -6,9 +6,6 @@
"use strict";
/**
* @template K
* @template V
*
* The StackedCacheMap is a data structure designed as an alternative to a Map
* in situations where you need to handle multiple item additions and
* frequently access the largest map.
@@ -19,7 +16,6 @@
* It has a fallback Map that is used when the map to be added is mutable.
*
* Note: `delete` and `has` are not supported for performance reasons.
*
* @example
* ```js
* const map = new StackedCacheMap();
@@ -31,6 +27,8 @@
* console.log(key, value);
* }
* ```
* @template K
* @template V
*/
class StackedCacheMap {
constructor() {
@@ -94,7 +92,7 @@ class StackedCacheMap {
/**
* @param {K} item the key of the element to return
* @returns {V} the value of the element
* @returns {V | undefined} the value of the element
*/
get(item) {
for (const map of this.stack) {
@@ -130,7 +128,7 @@ class StackedCacheMap {
next() {
let result = current.next();
while (result.done && iterators.length > 0) {
current = iterators.pop();
current = /** @type {IterableIterator<[K, V]>} */ (iterators.pop());
result = current.next();
}
return result;

View File

@@ -29,9 +29,8 @@ const extractPair = pair => {
const val = pair[1];
if (val === UNDEFINED_MARKER || val === TOMBSTONE) {
return [key, undefined];
} else {
return /** @type {[K, Cell<V>]} */ (pair);
}
return /** @type {[K, Cell<V>]} */ (pair);
};
/**
@@ -116,7 +115,6 @@ class StackedMap {
}
this.map.set(item, TOMBSTONE);
}
return undefined;
}
_compress() {

View File

@@ -17,7 +17,6 @@
* to create a hash of the current state of the compilation. By XOR'ing the Module hashes, it
* doesn't matter if the Module hashes are sorted or not. This is useful because it allows us to avoid sorting the
* Module hashes.
*
* @example
* ```js
* const xor = new StringXor();
@@ -25,7 +24,6 @@
* xor.add('world');
* console.log(xor.toString());
* ```
*
* @example
* ```js
* const xor = new StringXor();
@@ -44,7 +42,6 @@ class StringXor {
/**
* Adds a string to the current StringXor object.
*
* @param {string} str string
* @returns {void}
*/
@@ -84,7 +81,6 @@ class StringXor {
* here because "latin1" encoding is a single-byte encoding that can represent all characters in the
* [ISO-8859-1 character set](https://en.wikipedia.org/wiki/ISO/IEC_8859-1). This is useful when working
* with binary data that needs to be represented as a string.
*
* @returns {string} Returns a string that represents the current state of the StringXor object.
*/
toString() {
@@ -94,7 +90,6 @@ class StringXor {
/**
* Updates the hash with the current state of the StringXor object.
*
* @param {Hash} hash Hash instance
*/
updateHash(hash) {

View File

@@ -57,7 +57,7 @@ class TupleQueue {
this._set.delete(...value);
return value;
}
return undefined;
return;
}
this._set.delete(...result.value);
return result.value;

View File

@@ -9,7 +9,11 @@
* @template {any[]} T
*/
class TupleSet {
/**
* @param {Iterable<T>=} init init
*/
constructor(init) {
/** @type {Map<T, TODO>} */
this._map = new Map();
this.size = 0;
if (init) {
@@ -62,7 +66,7 @@ class TupleSet {
}
const beforeLast = args[args.length - 2];
let set = map.get(beforeLast);
const set = map.get(beforeLast);
if (set === undefined) {
return false;
}
@@ -86,7 +90,7 @@ class TupleSet {
}
const beforeLast = args[args.length - 2];
let set = map.get(beforeLast);
const set = map.get(beforeLast);
if (set === undefined) {
return;
}
@@ -101,10 +105,17 @@ class TupleSet {
* @returns {Iterator<T>} iterator
*/
[Symbol.iterator]() {
/** @type {TODO[]} */
const iteratorStack = [];
/** @type {T[]} */
const tuple = [];
let currentSetIterator = undefined;
/** @type {Iterator<T> | undefined} */
let currentSetIterator;
/**
* @param {TODO} it iterator
* @returns {boolean} result
*/
const next = it => {
const result = it.next();
if (result.done) {
@@ -118,9 +129,8 @@ class TupleSet {
if (value instanceof Set) {
currentSetIterator = value[Symbol.iterator]();
return true;
} else {
return next(value[Symbol.iterator]());
}
return next(value[Symbol.iterator]());
};
next(this._map[Symbol.iterator]());

View File

@@ -36,7 +36,7 @@ function getScheme(specifier) {
(start < aLowerCaseCharCode || start > zLowerCaseCharCode) &&
(start < aUpperCaseCharCode || start > zUpperCaseCharCode)
) {
return undefined;
return;
}
let i = 1;
@@ -49,12 +49,12 @@ function getScheme(specifier) {
ch === plusCharCode ||
ch === hyphenCharCode
) {
if (++i === specifier.length) return undefined;
if (++i === specifier.length) return;
ch = specifier.charCodeAt(i);
}
// Scheme must end with colon
if (ch !== colonCharCode) return undefined;
if (ch !== colonCharCode) return;
// Check for Windows absolute path
// https://url.spec.whatwg.org/#url-miscellaneous
@@ -67,7 +67,7 @@ function getScheme(specifier) {
nextChar === hashCharCode ||
nextChar === queryCharCode
) {
return undefined;
return;
}
}
@@ -80,8 +80,8 @@ function getScheme(specifier) {
*/
function getProtocol(specifier) {
const scheme = getScheme(specifier);
return scheme === undefined ? undefined : scheme + ":";
return scheme === undefined ? undefined : `${scheme}:`;
}
exports.getScheme = getScheme;
exports.getProtocol = getProtocol;
module.exports.getScheme = getScheme;
module.exports.getProtocol = getProtocol;

View File

@@ -83,7 +83,7 @@ class WeakTupleMap {
let node = this;
for (let i = 0; i < args.length; i++) {
node = node._peek(args[i]);
if (node === undefined) return undefined;
if (node === undefined) return;
}
return node._getValue();
}
@@ -158,12 +158,11 @@ class WeakTupleMap {
*/
_peek(thing) {
if (isWeakKey(thing)) {
if ((this.f & 4) !== 4) return undefined;
if ((this.f & 4) !== 4) return;
return /** @type {W<T, V>} */ (this.w).get(thing);
} else {
if ((this.f & 2) !== 2) return undefined;
return /** @type {M<T, V>} */ (this.m).get(thing);
}
if ((this.f & 2) !== 2) return;
return /** @type {M<T, V>} */ (this.m).get(thing);
}
/**
@@ -190,25 +189,24 @@ class WeakTupleMap {
/** @type {W<T, V>} */
(this.w).set(thing, newNode);
return newNode;
} else {
if ((this.f & 2) !== 2) {
const newMap = new Map();
this.f |= 2;
const newNode = new WeakTupleMap();
(this.m = newMap).set(thing, newNode);
return newNode;
}
const entry =
/** @type {M<T, V>} */
(this.m).get(thing);
if (entry !== undefined) {
return entry;
}
}
if ((this.f & 2) !== 2) {
const newMap = new Map();
this.f |= 2;
const newNode = new WeakTupleMap();
/** @type {M<T, V>} */
(this.m).set(thing, newNode);
(this.m = newMap).set(thing, newNode);
return newNode;
}
const entry =
/** @type {M<T, V>} */
(this.m).get(thing);
if (entry !== undefined) {
return entry;
}
const newNode = new WeakTupleMap();
/** @type {M<T, V>} */
(this.m).set(thing, newNode);
return newNode;
}
}

View File

@@ -22,7 +22,6 @@
* ```js
* function P(a,l,h,y,c){var i=l-1;while(l<=h){var m=(l+h)>>>1,x=a[m];if(c(x,y)<=0){i=m;l=m+1}else{h=m-1}}return i};
* ```
*
* @param {string} funcName The name of the function to be compiled.
* @param {string} predicate The predicate / comparison operator to be used in the binary search.
* @param {boolean} reversed Whether the search should be reversed.
@@ -43,7 +42,7 @@ const compileSearch = (funcName, predicate, reversed, extraArgs, earlyOut) => {
];
if (earlyOut) {
if (predicate.indexOf("c") < 0) {
if (!predicate.includes("c")) {
code.push(";if(x===y){return m}else if(x<=y){");
} else {
code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){");
@@ -70,7 +69,6 @@ const compileSearch = (funcName, predicate, reversed, extraArgs, earlyOut) => {
* A(): Performs a binary search on an array using the comparison operator specified.
* P(): Performs a binary search on an array using a _custom comparison function_
* `c(x,y)` **and** comparison operator specified by `predicate`.
*
* @param {BinarySearchPredicate} predicate The predicate / comparison operator to be used in the binary search.
* @param {boolean} reversed Whether the search should be reversed.
* @param {SearchPredicateSuffix} suffix The suffix to be used in the function name.
@@ -78,17 +76,11 @@ const compileSearch = (funcName, predicate, reversed, extraArgs, earlyOut) => {
* @returns {Function} The compiled binary search function.
*/
const compileBoundsSearch = (predicate, reversed, suffix, earlyOut) => {
const arg1 = compileSearch(
"A",
"x" + predicate + "y",
reversed,
["y"],
earlyOut
);
const arg1 = compileSearch("A", `x${predicate}y`, reversed, ["y"], earlyOut);
const arg2 = compileSearch(
"P",
"c(x,y)" + predicate + "0",
`c(x,y)${predicate}0`,
reversed,
["y", "c"],
earlyOut
@@ -97,6 +89,7 @@ const compileBoundsSearch = (predicate, reversed, suffix, earlyOut) => {
const fnHeader = "function dispatchBinarySearch";
const fnBody =
// eslint-disable-next-line no-multi-str
"(a,y,c,l,h){\
if(typeof(c)==='function'){\
return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)\
@@ -107,13 +100,13 @@ return dispatchBinarySearch";
const fnArgList = [arg1, arg2, fnHeader, suffix, fnBody, suffix];
const fnSource = fnArgList.join("");
// eslint-disable-next-line no-new-func
const result = new Function(fnSource);
return result();
};
/**
* These functions are used to perform binary searches on arrays.
*
* @example
* ```js
* const { gt, le} = require("./binarySearchBounds");

View File

@@ -23,7 +23,7 @@
* @param {Dependency} dependency dependency
* @returns {{trimmedIds: string[], trimmedRange: Range}} computed trimmed ids and cumulative range of those ids
*/
exports.getTrimmedIdsAndRange = (
module.exports.getTrimmedIdsAndRange = (
untrimmedIds,
untrimmedRange,
ranges,

View File

@@ -23,15 +23,17 @@ const DYNAMIC_INFO = Symbol("cleverMerge dynamic info");
* // when same arguments passed, gets the result from WeakMap and returns it.
* cachedCleverMerge({a: 1}, {a: 2})
* {a: 2}
* @param {T} first first object
* @param {O} second second object
* @param {T | null | undefined} first first object
* @param {O | null | undefined} second second object
* @returns {T & O | T | O} merged object of first and second object
*/
const cachedCleverMerge = (first, second) => {
if (second === undefined) return first;
if (first === undefined) return second;
if (typeof second !== "object" || second === null) return second;
if (typeof first !== "object" || first === null) return first;
if (second === undefined) return /** @type {T} */ (first);
if (first === undefined) return /** @type {O} */ (second);
if (typeof second !== "object" || second === null)
return /** @type {O} */ (second);
if (typeof first !== "object" || first === null)
return /** @type {T} */ (first);
let innerCache = mergeCache.get(first);
if (innerCache === undefined) {
@@ -80,11 +82,13 @@ const cachedSetProperty = (obj, property, value) => {
return /** @type {T} */ (result);
};
/** @typedef {Map<string, any>} ByValues */
/**
* @typedef {object} ObjectParsedPropertyEntry
* @property {any | undefined} base base value
* @property {string | undefined} byProperty the name of the selector property
* @property {Map<string, any>} byValues value depending on selector property, merged with base
* @property {ByValues} byValues value depending on selector property, merged with base
*/
/**
@@ -109,12 +113,17 @@ const cachedParseObject = obj => {
};
/**
* @param {object} obj the object
* @template {object} T
* @param {T} obj the object
* @returns {ParsedObject} parsed object
*/
const parseObject = obj => {
const info = new Map();
let dynamicInfo;
/**
* @param {string} p path
* @returns {Partial<ObjectParsedPropertyEntry>} object parsed property entry
*/
const getInfo = p => {
const entry = info.get(p);
if (entry !== undefined) return entry;
@@ -128,26 +137,33 @@ const parseObject = obj => {
};
for (const key of Object.keys(obj)) {
if (key.startsWith("by")) {
const byProperty = key;
const byObj = obj[byProperty];
const byProperty = /** @type {keyof T} */ (key);
const byObj = /** @type {object} */ (obj[byProperty]);
if (typeof byObj === "object") {
for (const byValue of Object.keys(byObj)) {
const obj = byObj[byValue];
const obj = byObj[/** @type {keyof (keyof T)} */ (byValue)];
for (const key of Object.keys(obj)) {
const entry = getInfo(key);
if (entry.byProperty === undefined) {
entry.byProperty = byProperty;
entry.byProperty = /** @type {string} */ (byProperty);
entry.byValues = new Map();
} else if (entry.byProperty !== byProperty) {
throw new Error(
`${byProperty} and ${entry.byProperty} for a single property is not supported`
`${/** @type {string} */ (byProperty)} and ${entry.byProperty} for a single property is not supported`
);
}
entry.byValues.set(byValue, obj[key]);
/** @type {ByValues} */
(entry.byValues).set(
byValue,
obj[/** @type {keyof (keyof T)} */ (key)]
);
if (byValue === "default") {
for (const otherByValue of Object.keys(byObj)) {
if (!entry.byValues.has(otherByValue))
entry.byValues.set(otherByValue, undefined);
if (
!(/** @type {ByValues} */ (entry.byValues).has(otherByValue))
)
/** @type {ByValues} */
(entry.byValues).set(otherByValue, undefined);
}
}
}
@@ -165,11 +181,11 @@ const parseObject = obj => {
}
} else {
const entry = getInfo(key);
entry.base = obj[key];
entry.base = obj[/** @type {keyof T} */ (key)];
}
} else {
const entry = getInfo(key);
entry.base = obj[key];
entry.base = obj[/** @type {keyof T} */ (key)];
}
}
return {
@@ -179,12 +195,13 @@ const parseObject = obj => {
};
/**
* @template {object} T
* @param {Map<string, ObjectParsedPropertyEntry>} info static properties (key is property name)
* @param {{ byProperty: string, fn: Function } | undefined} dynamicInfo dynamic part
* @returns {object} the object
* @returns {T} the object
*/
const serializeObject = (info, dynamicInfo) => {
const obj = {};
const obj = /** @type {T} */ ({});
// Setup byProperty structure
for (const entry of info.values()) {
if (entry.byProperty !== undefined) {
@@ -196,7 +213,7 @@ const serializeObject = (info, dynamicInfo) => {
}
for (const [key, entry] of info) {
if (entry.base !== undefined) {
obj[key] = entry.base;
obj[/** @type {keyof T} */ (key)] = entry.base;
}
// Fill byProperty structure
if (entry.byProperty !== undefined) {
@@ -229,7 +246,7 @@ const getValueType = value => {
} else if (value === DELETE) {
return VALUE_TYPE_DELETE;
} else if (Array.isArray(value)) {
if (value.lastIndexOf("...") !== -1) return VALUE_TYPE_ARRAY_EXTEND;
if (value.includes("...")) return VALUE_TYPE_ARRAY_EXTEND;
return VALUE_TYPE_ATOM;
} else if (
typeof value === "object" &&
@@ -473,7 +490,7 @@ const mergeSingleValue = (a, b, internalCaching) => {
case VALUE_TYPE_UNDEFINED:
return b;
case VALUE_TYPE_DELETE:
return b.filter(item => item !== "...");
return /** @type {any[]} */ (b).filter(item => item !== "...");
case VALUE_TYPE_ARRAY_EXTEND: {
const newArray = [];
for (const item of b) {
@@ -488,7 +505,9 @@ const mergeSingleValue = (a, b, internalCaching) => {
return newArray;
}
case VALUE_TYPE_OBJECT:
return b.map(item => (item === "..." ? a : item));
return /** @type {any[]} */ (b).map(item =>
item === "..." ? a : item
);
default:
throw new Error("Not implemented");
}
@@ -520,15 +539,22 @@ const removeOperations = (obj, keysToKeepOriginalValue = []) => {
case VALUE_TYPE_DELETE:
break;
case VALUE_TYPE_OBJECT:
newObj[key] = removeOperations(
/** @type {TODO} */ (value),
keysToKeepOriginalValue
);
newObj[/** @type {keyof T} */ (key)] =
/** @type {T[keyof T]} */
(
removeOperations(
/** @type {TODO} */ (value),
keysToKeepOriginalValue
)
);
break;
case VALUE_TYPE_ARRAY_EXTEND:
newObj[key] =
/** @type {any[]} */
(value).filter(i => i !== "...");
newObj[/** @type {keyof T} */ (key)] =
/** @type {T[keyof T]} */
(
/** @type {any[]} */
(value).filter(i => i !== "...")
);
break;
default:
newObj[/** @type {keyof T} */ (key)] = value;
@@ -550,21 +576,21 @@ const resolveByProperty = (obj, byProperty, ...values) => {
if (typeof obj !== "object" || obj === null || !(byProperty in obj)) {
return obj;
}
const { [byProperty]: _byValue, ..._remaining } = /** @type {object} */ (obj);
const { [byProperty]: _byValue, ..._remaining } = obj;
const remaining = /** @type {T} */ (_remaining);
const byValue = /** @type {Record<string, T> | function(...any[]): T} */ (
_byValue
);
const byValue =
/** @type {Record<string, T> | function(...any[]): T} */
(_byValue);
if (typeof byValue === "object") {
const key = values[0];
if (key in byValue) {
return cachedCleverMerge(remaining, byValue[key]);
} else if ("default" in byValue) {
return cachedCleverMerge(remaining, byValue.default);
} else {
return /** @type {T} */ (remaining);
}
return remaining;
} else if (typeof byValue === "function") {
// eslint-disable-next-line prefer-spread
const result = byValue.apply(null, values);
return cachedCleverMerge(
remaining,
@@ -573,9 +599,9 @@ const resolveByProperty = (obj, byProperty, ...values) => {
}
};
exports.cachedSetProperty = cachedSetProperty;
exports.cachedCleverMerge = cachedCleverMerge;
exports.cleverMerge = cleverMerge;
exports.resolveByProperty = resolveByProperty;
exports.removeOperations = removeOperations;
exports.DELETE = DELETE;
module.exports.cachedSetProperty = cachedSetProperty;
module.exports.cachedCleverMerge = cachedCleverMerge;
module.exports.cleverMerge = cleverMerge;
module.exports.resolveByProperty = resolveByProperty;
module.exports.removeOperations = removeOperations;
module.exports.DELETE = DELETE;

View File

@@ -10,14 +10,26 @@ const { compareRuntime } = require("./runtime");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Chunk").ChunkId} ChunkId */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @template T @typedef {function(T, T): -1|0|1} Comparator */
/** @template TArg @template T @typedef {function(TArg, T, T): -1|0|1} RawParameterizedComparator */
/** @template TArg @template T @typedef {function(TArg): Comparator<T>} ParameterizedComparator */
/**
* @template T
* @typedef {function(T, T): -1|0|1} Comparator
*/
/**
* @template TArg
* @template T
* @typedef {function(TArg, T, T): -1|0|1} RawParameterizedComparator
*/
/**
* @template TArg
* @template T
* @typedef {function(TArg): Comparator<T>} ParameterizedComparator
*/
/**
* @template T
@@ -46,21 +58,16 @@ const createCachedParameterizedComparator = fn => {
* @param {Chunk} b chunk
* @returns {-1|0|1} compare result
*/
exports.compareChunksById = (a, b) => {
return compareIds(
/** @type {ChunkId} */ (a.id),
/** @type {ChunkId} */ (b.id)
);
};
module.exports.compareChunksById = (a, b) =>
compareIds(/** @type {ChunkId} */ (a.id), /** @type {ChunkId} */ (b.id));
/**
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
exports.compareModulesByIdentifier = (a, b) => {
return compareIds(a.identifier(), b.identifier());
};
module.exports.compareModulesByIdentifier = (a, b) =>
compareIds(a.identifier(), b.identifier());
/**
* @param {ChunkGraph} chunkGraph the chunk graph
@@ -68,11 +75,13 @@ exports.compareModulesByIdentifier = (a, b) => {
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
const compareModulesById = (chunkGraph, a, b) => {
return compareIds(chunkGraph.getModuleId(a), chunkGraph.getModuleId(b));
};
const compareModulesById = (chunkGraph, a, b) =>
compareIds(
/** @type {ModuleId} */ (chunkGraph.getModuleId(a)),
/** @type {ModuleId} */ (chunkGraph.getModuleId(b))
);
/** @type {ParameterizedComparator<ChunkGraph, Module>} */
exports.compareModulesById =
module.exports.compareModulesById =
createCachedParameterizedComparator(compareModulesById);
/**
@@ -88,7 +97,7 @@ const compareNumbers = (a, b) => {
if (a > b) return 1;
return 0;
};
exports.compareNumbers = compareNumbers;
module.exports.compareNumbers = compareNumbers;
/**
* @param {string} a string
@@ -160,7 +169,7 @@ const compareStringsNumeric = (a, b) => {
return 0;
};
exports.compareStringsNumeric = compareStringsNumeric;
module.exports.compareStringsNumeric = compareStringsNumeric;
/**
* @param {ModuleGraph} moduleGraph the module graph
@@ -177,7 +186,7 @@ const compareModulesByPostOrderIndexOrIdentifier = (moduleGraph, a, b) => {
return compareIds(a.identifier(), b.identifier());
};
/** @type {ParameterizedComparator<ModuleGraph, Module>} */
exports.compareModulesByPostOrderIndexOrIdentifier =
module.exports.compareModulesByPostOrderIndexOrIdentifier =
createCachedParameterizedComparator(
compareModulesByPostOrderIndexOrIdentifier
);
@@ -197,7 +206,7 @@ const compareModulesByPreOrderIndexOrIdentifier = (moduleGraph, a, b) => {
return compareIds(a.identifier(), b.identifier());
};
/** @type {ParameterizedComparator<ModuleGraph, Module>} */
exports.compareModulesByPreOrderIndexOrIdentifier =
module.exports.compareModulesByPreOrderIndexOrIdentifier =
createCachedParameterizedComparator(
compareModulesByPreOrderIndexOrIdentifier
);
@@ -209,14 +218,16 @@ exports.compareModulesByPreOrderIndexOrIdentifier =
* @returns {-1|0|1} compare result
*/
const compareModulesByIdOrIdentifier = (chunkGraph, a, b) => {
const cmp = compareIds(chunkGraph.getModuleId(a), chunkGraph.getModuleId(b));
const cmp = compareIds(
/** @type {ModuleId} */ (chunkGraph.getModuleId(a)),
/** @type {ModuleId} */ (chunkGraph.getModuleId(b))
);
if (cmp !== 0) return cmp;
return compareIds(a.identifier(), b.identifier());
};
/** @type {ParameterizedComparator<ChunkGraph, Module>} */
exports.compareModulesByIdOrIdentifier = createCachedParameterizedComparator(
compareModulesByIdOrIdentifier
);
module.exports.compareModulesByIdOrIdentifier =
createCachedParameterizedComparator(compareModulesByIdOrIdentifier);
/**
* @param {ChunkGraph} chunkGraph the chunk graph
@@ -224,11 +235,10 @@ exports.compareModulesByIdOrIdentifier = createCachedParameterizedComparator(
* @param {Chunk} b chunk
* @returns {-1|0|1} compare result
*/
const compareChunks = (chunkGraph, a, b) => {
return chunkGraph.compareChunks(a, b);
};
const compareChunks = (chunkGraph, a, b) => chunkGraph.compareChunks(a, b);
/** @type {ParameterizedComparator<ChunkGraph, Chunk>} */
exports.compareChunks = createCachedParameterizedComparator(compareChunks);
module.exports.compareChunks =
createCachedParameterizedComparator(compareChunks);
/**
* @param {string|number} a first id
@@ -244,7 +254,7 @@ const compareIds = (a, b) => {
return 0;
};
exports.compareIds = compareIds;
module.exports.compareIds = compareIds;
/**
* @param {string} a first string
@@ -257,20 +267,16 @@ const compareStrings = (a, b) => {
return 0;
};
exports.compareStrings = compareStrings;
module.exports.compareStrings = compareStrings;
/**
* @param {ChunkGroup} a first chunk group
* @param {ChunkGroup} b second chunk group
* @returns {-1|0|1} compare result
*/
const compareChunkGroupsByIndex = (a, b) => {
return /** @type {number} */ (a.index) < /** @type {number} */ (b.index)
? -1
: 1;
};
exports.compareChunkGroupsByIndex = compareChunkGroupsByIndex;
const compareChunkGroupsByIndex = (a, b) =>
/** @type {number} */ (a.index) < /** @type {number} */ (b.index) ? -1 : 1;
module.exports.compareChunkGroupsByIndex = compareChunkGroupsByIndex;
/**
* @template K1 {Object}
@@ -294,7 +300,7 @@ class TwoKeyWeakMap {
get(key1, key2) {
const childMap = this._map.get(key1);
if (childMap === undefined) {
return undefined;
return;
}
return childMap.get(key2);
}
@@ -347,7 +353,7 @@ const concatComparators = (c1, c2, ...cRest) => {
concatComparatorsCache.set(c1, c2, result);
return result;
};
exports.concatComparators = concatComparators;
module.exports.concatComparators = concatComparators;
/**
* @template A, B
@@ -380,17 +386,16 @@ const compareSelect = (getter, comparator) => {
return comparator(aValue, bValue);
}
return -1;
} else {
if (bValue !== undefined && bValue !== null) {
return 1;
}
return 0;
}
if (bValue !== undefined && bValue !== null) {
return 1;
}
return 0;
};
compareSelectCache.set(getter, comparator, result);
return result;
};
exports.compareSelect = compareSelect;
module.exports.compareSelect = compareSelect;
/** @type {WeakMap<Comparator<any>, Comparator<Iterable<any>>>} */
const compareIteratorsCache = new WeakMap();
@@ -426,7 +431,7 @@ const compareIterables = elementComparator => {
compareIteratorsCache.set(elementComparator, result);
return result;
};
exports.compareIterables = compareIterables;
module.exports.compareIterables = compareIterables;
// TODO this is no longer needed when minimum node.js version is >= 12
// since these versions ship with a stable sort function
@@ -435,7 +440,7 @@ exports.compareIterables = compareIterables;
* @param {Iterable<T>} iterable original ordered list
* @returns {Comparator<T>} comparator
*/
exports.keepOriginalOrder = iterable => {
module.exports.keepOriginalOrder = iterable => {
/** @type {Map<T, number>} */
const map = new Map();
let i = 0;
@@ -453,8 +458,8 @@ exports.keepOriginalOrder = iterable => {
* @param {ChunkGraph} chunkGraph the chunk graph
* @returns {Comparator<Chunk>} comparator
*/
exports.compareChunksNatural = chunkGraph => {
const cmpFn = exports.compareModulesById(chunkGraph);
module.exports.compareChunksNatural = chunkGraph => {
const cmpFn = module.exports.compareModulesById(chunkGraph);
const cmpIterableFn = compareIterables(cmpFn);
return concatComparators(
compareSelect(
@@ -479,9 +484,9 @@ exports.compareChunksNatural = chunkGraph => {
* @param {DependencyLocation} b A location node
* @returns {-1|0|1} sorting comparator value
*/
exports.compareLocations = (a, b) => {
let isObjectA = typeof a === "object" && a !== null;
let isObjectB = typeof b === "object" && b !== null;
module.exports.compareLocations = (a, b) => {
const isObjectA = typeof a === "object" && a !== null;
const isObjectB = typeof b === "object" && b !== null;
if (!isObjectA || !isObjectB) {
if (isObjectA) return 1;
if (isObjectB) return -1;

View File

@@ -9,16 +9,14 @@
* @param {string} str string
* @returns {string} quoted meta
*/
const quoteMeta = str => {
return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
};
const quoteMeta = str => str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
/**
* @param {string} str string
* @returns {string} string
*/
const toSimpleString = str => {
if (`${+str}` === str) {
if (`${Number(str)}` === str) {
return str;
}
return JSON.stringify(str);
@@ -52,9 +50,8 @@ const compileBooleanMatcherFromLists = (positiveItems, negativeItems) => {
const negativeRegexp = itemsToRegexp(negativeItems);
if (positiveRegexp.length <= negativeRegexp.length) {
return value => `/^${positiveRegexp}$/.test(${value})`;
} else {
return value => `!/^${negativeRegexp}$/.test(${value})`;
}
return value => `!/^${negativeRegexp}$/.test(${value})`;
};
/**

View File

@@ -12,7 +12,7 @@
* @param {CssGeneratorExportsConvention | undefined} convention convention
* @returns {string[]} results
*/
exports.cssExportConvention = (input, convention) => {
module.exports.cssExportConvention = (input, convention) => {
const set = new Set();
if (typeof convention === "function") {
set.add(convention(input));
@@ -20,20 +20,20 @@ exports.cssExportConvention = (input, convention) => {
switch (convention) {
case "camel-case": {
set.add(input);
set.add(exports.camelCase(input));
set.add(module.exports.camelCase(input));
break;
}
case "camel-case-only": {
set.add(exports.camelCase(input));
set.add(module.exports.camelCase(input));
break;
}
case "dashes": {
set.add(input);
set.add(exports.dashesCamelCase(input));
set.add(module.exports.dashesCamelCase(input));
break;
}
case "dashes-only": {
set.add(exports.dashesCamelCase(input));
set.add(module.exports.dashesCamelCase(input));
break;
}
case "as-is": {
@@ -50,18 +50,15 @@ exports.cssExportConvention = (input, convention) => {
* @param {string} input input
* @returns {string} result
*/
exports.dashesCamelCase = input => {
return input.replace(/-+(\w)/g, (match, firstLetter) =>
firstLetter.toUpperCase()
);
};
module.exports.dashesCamelCase = input =>
input.replace(/-+(\w)/g, (match, firstLetter) => firstLetter.toUpperCase());
// Copy from css-loader
/**
* @param {string} input input
* @returns {string} result
*/
exports.camelCase = input => {
module.exports.camelCase = input => {
let result = input.trim();
if (result.length === 0) {

View File

@@ -7,20 +7,33 @@
const memoize = require("./memoize");
/** @typedef {import("schema-utils/declarations/validate").ValidationErrorConfiguration} ValidationErrorConfiguration */
/** @typedef {import("./fs").JsonObject} JsonObject */
const getValidate = memoize(() => require("schema-utils").validate);
/**
* @template {object | object[]} T
* @param {(function(T): boolean) | undefined} check check
* @param {() => JsonObject} getSchema get schema fn
* @param {ValidationErrorConfiguration} options options
* @returns {function(T=): void} validate
*/
const createSchemaValidation = (check, getSchema, options) => {
getSchema = memoize(getSchema);
return value => {
if (check && !check(value)) {
getValidate()(getSchema(), value, options);
if (check) {
require("util").deprecate(
() => {},
"webpack bug: Pre-compiled schema reports error while real schema is happy. This has performance drawbacks.",
"DEP_WEBPACK_PRE_COMPILED_SCHEMA_INVALID"
)();
}
if (check && !check(/** @type {T} */ (value))) {
getValidate()(
getSchema(),
/** @type {object | object[]} */
(value),
options
);
require("util").deprecate(
() => {},
"webpack bug: Pre-compiled schema reports error while real schema is happy. This has performance drawbacks.",
"DEP_WEBPACK_PRE_COMPILED_SCHEMA_INVALID"
)();
}
};
};

View File

@@ -128,26 +128,29 @@ class DebugHash extends Hash {
* @returns {string|Buffer} digest
*/
digest(encoding) {
return Buffer.from("@webpack-debug-digest@" + this.string).toString("hex");
return Buffer.from(`@webpack-debug-digest@${this.string}`).toString("hex");
}
}
/** @type {typeof import("crypto") | undefined} */
let crypto = undefined;
let crypto;
/** @type {typeof import("./hash/xxhash64") | undefined} */
let createXXHash64 = undefined;
let createXXHash64;
/** @type {typeof import("./hash/md4") | undefined} */
let createMd4 = undefined;
let createMd4;
/** @type {typeof import("./hash/BatchedHash") | undefined} */
let BatchedHash = undefined;
let BatchedHash;
/** @typedef {string | typeof Hash} Algorithm */
/**
* Creates a hash by name or function
* @param {string | typeof Hash} algorithm the algorithm name or a constructor creating a hash
* @param {Algorithm} algorithm the algorithm name or a constructor creating a hash
* @returns {Hash} the hash
*/
module.exports = algorithm => {
if (typeof algorithm === "function") {
// eslint-disable-next-line new-cap
return new BulkUpdateDecorator(() => new algorithm());
}
switch (algorithm) {

View File

@@ -15,7 +15,10 @@ const deprecationCache = new Map();
* @property {true} _fakeHook it's a fake hook
*/
/** @template T @typedef {T & FakeHookMarker} FakeHook<T> */
/**
* @template T
* @typedef {T & FakeHookMarker} FakeHook<T>
*/
/**
* @param {string} message deprecation message
@@ -28,7 +31,7 @@ const createDeprecation = (message, code) => {
const fn = util.deprecate(
() => {},
message,
"DEP_WEBPACK_DEPRECATION_" + code
`DEP_WEBPACK_DEPRECATION_${code}`
);
deprecationCache.set(message, fn);
return fn;
@@ -69,7 +72,7 @@ const DISABLED_METHODS = [
* @param {string} name property name
* @returns {void}
*/
exports.arrayToSetDeprecation = (set, name) => {
module.exports.arrayToSetDeprecation = (set, name) => {
for (const method of COPY_METHODS) {
if (set[method]) continue;
const d = createDeprecation(
@@ -84,7 +87,11 @@ exports.arrayToSetDeprecation = (set, name) => {
set[method] = function () {
d();
const array = Array.from(this);
return Array.prototype[method].apply(array, arguments);
return Array.prototype[/** @type {keyof COPY_METHODS} */ (method)].apply(
array,
// eslint-disable-next-line prefer-rest-params
arguments
);
};
}
const dPush = createDeprecation(
@@ -106,6 +113,7 @@ exports.arrayToSetDeprecation = (set, name) => {
*/
set.push = function () {
dPush();
// eslint-disable-next-line prefer-rest-params
for (const item of Array.from(arguments)) {
this.add(item);
}
@@ -128,13 +136,13 @@ exports.arrayToSetDeprecation = (set, name) => {
* @this {Set<any>} a Set
* @returns {any} the value at this location
*/
// eslint-disable-next-line func-style
const fn = function () {
dIndexer();
let i = 0;
for (const item of this) {
if (i++ === index) return item;
}
return undefined;
};
return fn;
};
@@ -171,14 +179,29 @@ exports.arrayToSetDeprecation = (set, name) => {
set[Symbol.isConcatSpreadable] = true;
};
exports.createArrayToSetDeprecationSet = name => {
/**
* @template T
* @param {string} name name
* @returns {{ new <T = any>(values?: readonly T[] | null): SetDeprecatedArray<T> }} SetDeprecatedArray
*/
module.exports.createArrayToSetDeprecationSet = name => {
let initialized = false;
/**
* @template T
*/
class SetDeprecatedArray extends Set {
/**
* @param {readonly T[] | null=} items items
*/
constructor(items) {
super(items);
if (!initialized) {
initialized = true;
exports.arrayToSetDeprecation(SetDeprecatedArray.prototype, name);
module.exports.arrayToSetDeprecation(
SetDeprecatedArray.prototype,
name
);
}
}
}
@@ -186,41 +209,77 @@ exports.createArrayToSetDeprecationSet = name => {
};
/**
* @template T
* @param {object} obj object
* @template {object} T
* @param {T} obj object
* @param {string} name property name
* @param {string} code deprecation code
* @param {string} note additional note
* @returns {object} frozen object with deprecation when modifying
* @returns {Proxy<T>} frozen object with deprecation when modifying
*/
exports.soonFrozenObjectDeprecation = (obj, name, code, note = "") => {
module.exports.soonFrozenObjectDeprecation = (obj, name, code, note = "") => {
const message = `${name} will be frozen in future, all modifications are deprecated.${
note && `\n${note}`
}`;
return new Proxy(obj, {
set: util.deprecate(
(target, property, value, receiver) =>
Reflect.set(target, property, value, receiver),
message,
code
),
defineProperty: util.deprecate(
(target, property, descriptor) =>
Reflect.defineProperty(target, property, descriptor),
message,
code
),
deleteProperty: util.deprecate(
(target, property) => Reflect.deleteProperty(target, property),
message,
code
),
setPrototypeOf: util.deprecate(
(target, proto) => Reflect.setPrototypeOf(target, proto),
message,
code
)
});
return /** @type {Proxy<T>} */ (
new Proxy(/** @type {object} */ (obj), {
set: util.deprecate(
/**
* @param {T} target target
* @param {string | symbol} property property
* @param {any} value value
* @param {any} receiver receiver
* @returns {boolean} result
*/
(target, property, value, receiver) =>
Reflect.set(
/** @type {object} */ (target),
property,
value,
receiver
),
message,
code
),
defineProperty: util.deprecate(
/**
* @param {T} target target
* @param {string | symbol} property property
* @param {PropertyDescriptor} descriptor descriptor
* @returns {boolean} result
*/
(target, property, descriptor) =>
Reflect.defineProperty(
/** @type {object} */ (target),
property,
descriptor
),
message,
code
),
deleteProperty: util.deprecate(
/**
* @param {T} target target
* @param {string | symbol} property property
* @returns {boolean} result
*/
(target, property) =>
Reflect.deleteProperty(/** @type {object} */ (target), property),
message,
code
),
setPrototypeOf: util.deprecate(
/**
* @param {T} target target
* @param {object | null} proto proto
* @returns {boolean} result
*/
(target, proto) =>
Reflect.setPrototypeOf(/** @type {object} */ (target), proto),
message,
code
)
})
);
};
/**
@@ -253,23 +312,32 @@ const deprecateAllProperties = (obj, message, code) => {
enumerable: descriptor.enumerable,
get: util.deprecate(() => value, message, code),
set: descriptor.writable
? util.deprecate(v => (value = v), message, code)
? util.deprecate(
/**
* @template T
* @param {T} v value
* @returns {T} result
*/
v => (value = v),
message,
code
)
: undefined
});
}
}
return /** @type {T} */ (newObj);
};
exports.deprecateAllProperties = deprecateAllProperties;
module.exports.deprecateAllProperties = deprecateAllProperties;
/**
* @template T
* @template {object} T
* @param {T} fakeHook fake hook implementation
* @param {string=} message deprecation message (not deprecated when unset)
* @param {string=} code deprecation code (not deprecated when unset)
* @returns {FakeHook<T>} fake hook which redirects
*/
exports.createFakeHook = (fakeHook, message, code) => {
module.exports.createFakeHook = (fakeHook, message, code) => {
if (message && code) {
fakeHook = deprecateAllProperties(fakeHook, message, code);
}

View File

@@ -25,7 +25,6 @@
// 3.2% that 5 or more groups are invalidated
/**
*
* @param {string} a key
* @param {string} b key
* @returns {number} the similarity as number
@@ -116,9 +115,7 @@ const isTooBig = (size, maxSize) => {
const s = size[key];
if (s === 0) continue;
const maxSizeValue = maxSize[key];
if (typeof maxSizeValue === "number") {
if (s > maxSizeValue) return true;
}
if (typeof maxSizeValue === "number" && s > maxSizeValue) return true;
}
return false;
};
@@ -133,9 +130,7 @@ const isTooSmall = (size, minSize) => {
const s = size[key];
if (s === 0) continue;
const minSizeValue = minSize[key];
if (typeof minSizeValue === "number") {
if (s < minSizeValue) return true;
}
if (typeof minSizeValue === "number" && s < minSizeValue) return true;
}
return false;
};
@@ -151,9 +146,7 @@ const getTooSmallTypes = (size, minSize) => {
const s = size[key];
if (s === 0) continue;
const minSizeValue = minSize[key];
if (typeof minSizeValue === "number") {
if (s < minSizeValue) types.add(key);
}
if (typeof minSizeValue === "number" && s < minSizeValue) types.add(key);
}
return types;
};
@@ -236,14 +229,14 @@ class Group {
newSimilarities.push(
lastNode === this.nodes[i - 1]
? /** @type {number[]} */ (this.similarities)[i - 1]
: similarity(lastNode.key, node.key)
: similarity(/** @type {Node<T>} */ (lastNode).key, node.key)
);
}
newNodes.push(node);
lastNode = node;
}
}
if (resultNodes.length === this.nodes.length) return undefined;
if (resultNodes.length === this.nodes.length) return;
this.nodes = newNodes;
this.similarities = newSimilarities;
this.size = sumSize(newNodes);
@@ -260,7 +253,7 @@ const getSimilarities = nodes => {
// calculate similarities between lexically adjacent nodes
/** @type {number[]} */
const similarities = [];
let last = undefined;
let last;
for (const node of nodes) {
if (last !== undefined) {
similarities.push(similarity(last.key, node.key));
@@ -371,9 +364,8 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
result.push(new Group(problemNodes, null));
}
return true;
} else {
return false;
}
return false;
};
if (initialGroup.nodes.length > 0) {
@@ -398,14 +390,14 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
// going minSize from left and right
// at least one node need to be included otherwise we get stuck
let left = 1;
let leftSize = Object.create(null);
const leftSize = Object.create(null);
addSizeTo(leftSize, group.nodes[0].size);
while (left < group.nodes.length && isTooSmall(leftSize, minSize)) {
addSizeTo(leftSize, group.nodes[left].size);
left++;
}
let right = group.nodes.length - 2;
let rightSize = Object.create(null);
const rightSize = Object.create(null);
addSizeTo(rightSize, group.nodes[group.nodes.length - 1].size);
while (right >= 0 && isTooSmall(rightSize, minSize)) {
addSizeTo(rightSize, group.nodes[right].size);
@@ -453,7 +445,7 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
let best = -1;
let bestSimilarity = Infinity;
let pos = left;
let rightSize = sumSize(group.nodes.slice(pos));
const rightSize = sumSize(group.nodes.slice(pos));
// pos v v right
// [ O O O ] O O O [ O O O ]
@@ -536,12 +528,13 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
}
// return the results
return result.map(group => {
/** @type {GroupedItems<T>} */
return {
key: group.key,
items: group.nodes.map(node => node.item),
size: group.size
};
});
return result.map(
group =>
/** @type {GroupedItems<T>} */
({
key: group.key,
items: group.nodes.map(node => node.item),
size: group.size
})
);
};

View File

@@ -225,7 +225,7 @@ module.exports = (items, getDependencies) => {
// When roots were found, return them
if (roots.size > 0) {
return Array.from(roots, r => r.item);
} else {
throw new Error("Implementation of findGraphRoots is broken");
}
throw new Error("Implementation of findGraphRoots is broken");
};

78
node_modules/webpack/lib/util/fs.js generated vendored
View File

@@ -80,23 +80,28 @@ const path = require("path");
/** @typedef {function(NodeJS.ErrnoException | null, number=): void} NumberCallback */
/** @typedef {function(NodeJS.ErrnoException | Error | null, JsonObject=): void} ReadJsonCallback */
/** @typedef {Map<string, FileSystemInfoEntry | "ignore">} TimeInfoEntries */
/**
* @typedef {object} WatcherInfo
* @property {Set<string>} changes get current aggregated changes that have not yet send to callback
* @property {Set<string>} removals get current aggregated removals that have not yet send to callback
* @property {Map<string, FileSystemInfoEntry | "ignore">} fileTimeInfoEntries get info about files
* @property {Map<string, FileSystemInfoEntry | "ignore">} contextTimeInfoEntries get info about directories
* @property {Set<string> | null} changes get current aggregated changes that have not yet send to callback
* @property {Set<string> | null} removals get current aggregated removals that have not yet send to callback
* @property {TimeInfoEntries} fileTimeInfoEntries get info about files
* @property {TimeInfoEntries} contextTimeInfoEntries get info about directories
*/
/** @typedef {Set<string>} Changes */
/** @typedef {Set<string>} Removals */
// TODO webpack 6 deprecate missing getInfo
/**
* @typedef {object} Watcher
* @property {function(): void} close closes the watcher and all underlying file watchers
* @property {function(): void} pause closes the watcher, but keeps underlying file watchers alive until the next watch call
* @property {function(): Set<string>=} getAggregatedChanges get current aggregated changes that have not yet send to callback
* @property {function(): Set<string>=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getFileTimeInfoEntries get info about files
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getContextTimeInfoEntries get info about directories
* @property {(function(): Changes | null)=} getAggregatedChanges get current aggregated changes that have not yet send to callback
* @property {(function(): Removals | null)=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
* @property {function(): TimeInfoEntries} getFileTimeInfoEntries get info about files
* @property {function(): TimeInfoEntries} getContextTimeInfoEntries get info about directories
* @property {function(): WatcherInfo=} getInfo get info about timestamps and changes
*/
@@ -107,7 +112,7 @@ const path = require("path");
* @param {Iterable<string>} missing watched existence entries
* @param {number} startTime timestamp of start time
* @param {WatchOptions} options options object
* @param {function(Error | null, Map<string, FileSystemInfoEntry | "ignore">, Map<string, FileSystemInfoEntry | "ignore">, Set<string>, Set<string>): void} callback aggregated callback
* @param {function(Error | null, TimeInfoEntries=, TimeInfoEntries=, Changes=, Removals=): void} callback aggregated callback
* @param {function(string, number): void} callbackUndelayed callback when the first change was detected
* @returns {Watcher} a watcher
*/
@@ -367,7 +372,7 @@ const path = require("path");
* @typedef {object} StreamOptions
* @property {(string | undefined)=} flags
* @property {(BufferEncoding | undefined)} encoding
* @property {(number | any | undefined)=} fd
* @property {(number | EXPECTED_ANY | undefined)=} fd
* @property {(number | undefined)=} mode
* @property {(boolean | undefined)=} autoClose
* @property {(boolean | undefined)=} emitClose
@@ -377,12 +382,12 @@ const path = require("path");
/**
* @typedef {object} FSImplementation
* @property {((...args: any[]) => any)=} open
* @property {((...args: any[]) => any)=} close
* @property {((...args: EXPECTED_ANY[]) => EXPECTED_ANY)=} open
* @property {((...args: EXPECTED_ANY[]) => EXPECTED_ANY)=} close
*/
/**
* @typedef {FSImplementation & { write: (...args: any[]) => any; close?: (...args: any[]) => any }} CreateWriteStreamFSImplementation
* @typedef {FSImplementation & { write: (...args: EXPECTED_ANY[]) => EXPECTED_ANY; close?: (...args: EXPECTED_ANY[]) => EXPECTED_ANY }} CreateWriteStreamFSImplementation
*/
/**
@@ -451,7 +456,6 @@ const path = require("path");
/** @typedef {InputFileSystem & OutputFileSystem & IntermediateFileSystemExtras} IntermediateFileSystem */
/**
*
* @param {InputFileSystem|OutputFileSystem|undefined} fs a file system
* @param {string} rootPath the root path
* @param {string} targetPath the target path
@@ -464,13 +468,12 @@ const relative = (fs, rootPath, targetPath) => {
return path.posix.relative(rootPath, targetPath);
} else if (path.win32.isAbsolute(rootPath)) {
return path.win32.relative(rootPath, targetPath);
} else {
throw new Error(
`${rootPath} is neither a posix nor a windows path, and there is no 'relative' method defined in the file system`
);
}
throw new Error(
`${rootPath} is neither a posix nor a windows path, and there is no 'relative' method defined in the file system`
);
};
exports.relative = relative;
module.exports.relative = relative;
/**
* @param {InputFileSystem|OutputFileSystem|undefined} fs a file system
@@ -485,13 +488,12 @@ const join = (fs, rootPath, filename) => {
return path.posix.join(rootPath, filename);
} else if (path.win32.isAbsolute(rootPath)) {
return path.win32.join(rootPath, filename);
} else {
throw new Error(
`${rootPath} is neither a posix nor a windows path, and there is no 'join' method defined in the file system`
);
}
throw new Error(
`${rootPath} is neither a posix nor a windows path, and there is no 'join' method defined in the file system`
);
};
exports.join = join;
module.exports.join = join;
/**
* @param {InputFileSystem|OutputFileSystem|undefined} fs a file system
@@ -505,13 +507,12 @@ const dirname = (fs, absPath) => {
return path.posix.dirname(absPath);
} else if (path.win32.isAbsolute(absPath)) {
return path.win32.dirname(absPath);
} else {
throw new Error(
`${absPath} is neither a posix nor a windows path, and there is no 'dirname' method defined in the file system`
);
}
throw new Error(
`${absPath} is neither a posix nor a windows path, and there is no 'dirname' method defined in the file system`
);
};
exports.dirname = dirname;
module.exports.dirname = dirname;
/**
* @param {OutputFileSystem} fs a file system
@@ -556,7 +557,7 @@ const mkdirp = (fs, p, callback) => {
callback();
});
};
exports.mkdirp = mkdirp;
module.exports.mkdirp = mkdirp;
/**
* @param {IntermediateFileSystem} fs a file system
@@ -583,7 +584,7 @@ const mkdirpSync = (fs, p) => {
}
}
};
exports.mkdirpSync = mkdirpSync;
module.exports.mkdirpSync = mkdirpSync;
/**
* @param {InputFileSystem} fs a file system
@@ -601,13 +602,13 @@ const readJson = (fs, p, callback) => {
let data;
try {
data = JSON.parse(/** @type {Buffer} */ (buf).toString("utf-8"));
} catch (e) {
return callback(/** @type {Error} */ (e));
} catch (err1) {
return callback(/** @type {Error} */ (err1));
}
return callback(null, data);
});
};
exports.readJson = readJson;
module.exports.readJson = readJson;
/**
* @param {InputFileSystem} fs a file system
@@ -624,8 +625,8 @@ const lstatReadlinkAbsolute = (fs, p, callback) => {
// we retry 2 times to catch this case before throwing the error
return doStat();
}
if (err || !target) return doStat();
const value = target.toString();
if (err) return callback(err);
const value = /** @type {string} */ (target).toString();
callback(null, join(fs, dirname(fs, p), value));
});
};
@@ -641,11 +642,10 @@ const lstatReadlinkAbsolute = (fs, p, callback) => {
callback(null, stats);
}
);
} else {
return fs.stat(p, callback);
}
return fs.stat(p, callback);
};
if ("lstat" in fs) return doStat();
doReadLink();
};
exports.lstatReadlinkAbsolute = lstatReadlinkAbsolute;
module.exports.lstatReadlinkAbsolute = lstatReadlinkAbsolute;

View File

@@ -7,7 +7,7 @@
const create = require("./wasm-hash");
//#region wasm code: md4 (../../../assembly/hash/md4.asm.ts) --initialMemory 1
// #region wasm code: md4 (../../../assembly/hash/md4.asm.ts) --initialMemory 1
const md4 = new WebAssembly.Module(
Buffer.from(
// 2154 bytes
@@ -15,6 +15,6 @@ const md4 = new WebAssembly.Module(
"base64"
)
);
//#endregion
// #endregion
module.exports = create.bind(null, md4, [], 64, 32);

View File

@@ -133,6 +133,10 @@ class WasmHash {
}
}
/**
* @param {BufferEncoding} type type
* @returns {Buffer | string} digest
*/
digest(type) {
const { exports, buffered, mem, digestSize } = this;
exports.final(buffered);
@@ -144,19 +148,26 @@ class WasmHash {
}
}
/**
* @param {TODO} wasmModule wasm module
* @param {WasmHash[]} instancesPool pool of instances
* @param {number} chunkSize size of data chunks passed to wasm
* @param {number} digestSize size of digest returned by wasm
* @returns {WasmHash} wasm hash
*/
const create = (wasmModule, instancesPool, chunkSize, digestSize) => {
if (instancesPool.length > 0) {
const old = instancesPool.pop();
const old = /** @type {WasmHash} */ (instancesPool.pop());
old.reset();
return old;
} else {
return new WasmHash(
new WebAssembly.Instance(wasmModule),
instancesPool,
chunkSize,
digestSize
);
}
return new WasmHash(
new WebAssembly.Instance(wasmModule),
instancesPool,
chunkSize,
digestSize
);
};
module.exports = create;

View File

@@ -7,7 +7,7 @@
const create = require("./wasm-hash");
//#region wasm code: xxhash64 (../../../assembly/hash/xxhash64.asm.ts) --initialMemory 1
// #region wasm code: xxhash64 (../../../assembly/hash/xxhash64.asm.ts) --initialMemory 1
const xxhash64 = new WebAssembly.Module(
Buffer.from(
// 1160 bytes
@@ -15,6 +15,6 @@ const xxhash64 = new WebAssembly.Module(
"base64"
)
);
//#endregion
// #endregion
module.exports = create.bind(null, xxhash64, [], 32, 16);

View File

@@ -85,24 +85,48 @@ const requestToAbsolute = (context, relativePath) => {
return relativePath;
};
/**
* @template T
* @typedef {function(string, object=): T} MakeCacheableResult
*/
/**
* @template T
* @typedef {function(string): T} BindCacheResultFn
*/
/**
* @template T
* @typedef {function(object): BindCacheResultFn<T>} BindCache
*/
/**
* @template T
* @param {(function(string): T)} realFn real function
* @returns {MakeCacheableResult<T> & { bindCache: BindCache<T> }} cacheable function
*/
const makeCacheable = realFn => {
/** @type {WeakMap<object, Map<string, ParsedResource>>} */
/**
* @template T
* @typedef {Map<string, T>} CacheItem
*/
/** @type {WeakMap<object, CacheItem<T>>} */
const cache = new WeakMap();
/**
* @param {object} associatedObjectForCache an object to which the cache will be attached
* @returns {CacheItem<T>} cache item
*/
const getCache = associatedObjectForCache => {
const entry = cache.get(associatedObjectForCache);
if (entry !== undefined) return entry;
/** @type {Map<string, ParsedResource>} */
/** @type {Map<string, T>} */
const map = new Map();
cache.set(associatedObjectForCache, map);
return map;
};
/**
* @param {string} str the path with query and fragment
* @param {object=} associatedObjectForCache an object to which the cache will be attached
* @returns {ParsedResource} parsed parts
*/
/** @type {MakeCacheableResult<T> & { bindCache: BindCache<T> }} */
const fn = (str, associatedObjectForCache) => {
if (!associatedObjectForCache) return realFn(str);
const cache = getCache(associatedObjectForCache);
@@ -113,8 +137,13 @@ const makeCacheable = realFn => {
return result;
};
/** @type {BindCache<T>} */
fn.bindCache = associatedObjectForCache => {
const cache = getCache(associatedObjectForCache);
/**
* @param {string} str string
* @returns {T} value
*/
return str => {
const entry = cache.get(str);
if (entry !== undefined) return entry;
@@ -127,16 +156,21 @@ const makeCacheable = realFn => {
return fn;
};
/** @typedef {function(string, string, object=): string} MakeCacheableWithContextResult */
/** @typedef {function(string, string): string} BindCacheForContextResultFn */
/** @typedef {function(string): string} BindContextCacheForContextResultFn */
/** @typedef {function(object=): BindCacheForContextResultFn} BindCacheForContext */
/** @typedef {function(string, object=): BindContextCacheForContextResultFn} BindContextCacheForContext */
/**
* @param {function(string, string): string} fn function
* @returns {MakeCacheableWithContextResult & { bindCache: BindCacheForContext, bindContextCache: BindContextCacheForContext }} cacheable function with context
*/
const makeCacheableWithContext = fn => {
/** @type {WeakMap<object, Map<string, Map<string, string>>>} */
const cache = new WeakMap();
/**
* @param {string} context context used to create relative path
* @param {string} identifier identifier used to create relative path
* @param {object=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} the returned relative path
*/
/** @type {MakeCacheableWithContextResult & { bindCache: BindCacheForContext, bindContextCache: BindContextCacheForContext }} */
const cachedFn = (context, identifier, associatedObjectForCache) => {
if (!associatedObjectForCache) return fn(context, identifier);
@@ -156,17 +190,13 @@ const makeCacheableWithContext = fn => {
if (cachedResult !== undefined) {
return cachedResult;
} else {
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
}
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
};
/**
* @param {object=} associatedObjectForCache an object to which the cache will be attached
* @returns {function(string, string): string} cached function
*/
/** @type {BindCacheForContext} */
cachedFn.bindCache = associatedObjectForCache => {
let innerCache;
if (associatedObjectForCache) {
@@ -195,21 +225,16 @@ const makeCacheableWithContext = fn => {
if (cachedResult !== undefined) {
return cachedResult;
} else {
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
}
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
};
return boundFn;
};
/**
* @param {string} context context used to create relative path
* @param {object=} associatedObjectForCache an object to which the cache will be attached
* @returns {function(string): string} cached function
*/
/** @type {BindContextCacheForContext} */
cachedFn.bindContextCache = (context, associatedObjectForCache) => {
let innerSubCache;
if (associatedObjectForCache) {
@@ -235,11 +260,10 @@ const makeCacheableWithContext = fn => {
const cachedResult = innerSubCache.get(identifier);
if (cachedResult !== undefined) {
return cachedResult;
} else {
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
}
const result = fn(context, identifier);
innerSubCache.set(identifier, result);
return result;
};
return boundFn;
@@ -249,64 +273,58 @@ const makeCacheableWithContext = fn => {
};
/**
*
* @param {string} context context for relative path
* @param {string} identifier identifier for path
* @returns {string} a converted relative path
*/
const _makePathsRelative = (context, identifier) => {
return identifier
const _makePathsRelative = (context, identifier) =>
identifier
.split(SEGMENTS_SPLIT_REGEXP)
.map(str => absoluteToRequest(context, str))
.join("");
};
exports.makePathsRelative = makeCacheableWithContext(_makePathsRelative);
module.exports.makePathsRelative = makeCacheableWithContext(_makePathsRelative);
/**
*
* @param {string} context context for relative path
* @param {string} identifier identifier for path
* @returns {string} a converted relative path
*/
const _makePathsAbsolute = (context, identifier) => {
return identifier
const _makePathsAbsolute = (context, identifier) =>
identifier
.split(SEGMENTS_SPLIT_REGEXP)
.map(str => requestToAbsolute(context, str))
.join("");
};
exports.makePathsAbsolute = makeCacheableWithContext(_makePathsAbsolute);
module.exports.makePathsAbsolute = makeCacheableWithContext(_makePathsAbsolute);
/**
* @param {string} context absolute context path
* @param {string} request any request string may containing absolute paths, query string, etc.
* @returns {string} a new request string avoiding absolute paths when possible
*/
const _contextify = (context, request) => {
return request
const _contextify = (context, request) =>
request
.split("!")
.map(r => absoluteToRequest(context, r))
.join("!");
};
const contextify = makeCacheableWithContext(_contextify);
exports.contextify = contextify;
module.exports.contextify = contextify;
/**
* @param {string} context absolute context path
* @param {string} request any request string
* @returns {string} a new request string using absolute paths when possible
*/
const _absolutify = (context, request) => {
return request
const _absolutify = (context, request) =>
request
.split("!")
.map(r => requestToAbsolute(context, r))
.join("!");
};
const absolutify = makeCacheableWithContext(_absolutify);
exports.absolutify = absolutify;
module.exports.absolutify = absolutify;
const PATH_QUERY_FRAGMENT_REGEXP =
/^((?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
@@ -320,7 +338,9 @@ const PATH_QUERY_REGEXP = /^((?:\0.|[^?\0])*)(\?.*)?$/;
* @returns {ParsedResource} parsed parts
*/
const _parseResource = str => {
const match = PATH_QUERY_FRAGMENT_REGEXP.exec(str);
const match =
/** @type {[string, string, string | undefined, string | undefined]} */
(/** @type {unknown} */ (PATH_QUERY_FRAGMENT_REGEXP.exec(str)));
return {
resource: str,
path: match[1].replace(/\0(.)/g, "$1"),
@@ -328,7 +348,7 @@ const _parseResource = str => {
fragment: match[3] || ""
};
};
exports.parseResource = makeCacheable(_parseResource);
module.exports.parseResource = makeCacheable(_parseResource);
/**
* Parse resource, skips fragment part
@@ -336,14 +356,16 @@ exports.parseResource = makeCacheable(_parseResource);
* @returns {ParsedResourceWithoutFragment} parsed parts
*/
const _parseResourceWithoutFragment = str => {
const match = PATH_QUERY_REGEXP.exec(str);
const match =
/** @type {[string, string, string | undefined]} */
(/** @type {unknown} */ (PATH_QUERY_REGEXP.exec(str)));
return {
resource: str,
path: match[1].replace(/\0(.)/g, "$1"),
query: match[2] ? match[2].replace(/\0(.)/g, "$1") : ""
};
};
exports.parseResourceWithoutFragment = makeCacheable(
module.exports.parseResourceWithoutFragment = makeCacheable(
_parseResourceWithoutFragment
);
@@ -353,7 +375,7 @@ exports.parseResourceWithoutFragment = makeCacheable(
* @param {boolean} enforceRelative true returns ./ for empty paths
* @returns {string} repeated ../ to leave the directory of the provided filename to be back on output dir
*/
exports.getUndoPath = (filename, outputPath, enforceRelative) => {
module.exports.getUndoPath = (filename, outputPath, enforceRelative) => {
let depth = -1;
let append = "";
outputPath = outputPath.replace(/[\\/]$/, "");
@@ -365,8 +387,8 @@ exports.getUndoPath = (filename, outputPath, enforceRelative) => {
const i = outputPath.lastIndexOf("/");
const j = outputPath.lastIndexOf("\\");
const pos = i < 0 ? j : j < 0 ? i : Math.max(i, j);
if (pos < 0) return outputPath + "/";
append = outputPath.slice(pos + 1) + "/" + append;
if (pos < 0) return `${outputPath}/`;
append = `${outputPath.slice(pos + 1)}/${append}`;
outputPath = outputPath.slice(0, pos);
}
} else if (part !== ".") {

View File

@@ -7,16 +7,38 @@
const { register } = require("./serialization");
/** @typedef {import("../serialization/ObjectMiddleware").Constructor} Constructor */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {{ serialize: (context: ObjectSerializerContext) => void, deserialize: (context: ObjectDeserializerContext) => void }} SerializableClass */
/**
* @template {SerializableClass} T
* @typedef {(new (...params: any[]) => T) & { deserialize?: (context: ObjectDeserializerContext) => T }} SerializableClassConstructor
*/
/**
* @template {SerializableClass} T
*/
class ClassSerializer {
/**
* @param {SerializableClassConstructor<T>} Constructor constructor
*/
constructor(Constructor) {
this.Constructor = Constructor;
}
/**
* @param {T} obj obj
* @param {ObjectSerializerContext} context context
*/
serialize(obj, context) {
obj.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
* @returns {T} obj
*/
deserialize(context) {
if (typeof this.Constructor.deserialize === "function") {
return this.Constructor.deserialize(context);
@@ -28,7 +50,8 @@ class ClassSerializer {
}
/**
* @param {Constructor} Constructor the constructor
* @template {Constructor} T
* @param {T} Constructor the constructor
* @param {string} request the request which will be required when deserializing
* @param {string | null} [name] the name to make multiple serializer unique when sharing a request
*/

View File

@@ -14,20 +14,19 @@
const memoize = fn => {
let cache = false;
/** @type {T | undefined} */
let result = undefined;
let result;
return () => {
if (cache) {
return /** @type {T} */ (result);
} else {
result = fn();
cache = true;
// Allow to clean up memory for fn
// and all dependent resources
// eslint-disable-next-line no-warning-comments
// @ts-ignore
fn = undefined;
return /** @type {T} */ (result);
}
result = fn();
cache = true;
// Allow to clean up memory for fn
// and all dependent resources
/** @type {FunctionReturning<T> | undefined} */
(fn) = undefined;
return /** @type {T} */ (result);
};
};

View File

@@ -1,79 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("eslint-scope").Reference} Reference */
/** @typedef {import("eslint-scope").Variable} Variable */
/** @typedef {import("../javascript/JavascriptParser").AnyNode} AnyNode */
/** @typedef {import("../javascript/JavascriptParser").Program} Program */
/**
* @param {Variable} variable variable
* @returns {Reference[]} references
*/
const getAllReferences = variable => {
let set = variable.references;
// Look for inner scope variables too (like in class Foo { t() { Foo } })
const identifiers = new Set(variable.identifiers);
for (const scope of variable.scope.childScopes) {
for (const innerVar of scope.variables) {
if (innerVar.identifiers.some(id => identifiers.has(id))) {
set = set.concat(innerVar.references);
break;
}
}
}
return set;
};
/**
* @param {Program | Program[]} ast ast
* @param {AnyNode} node node
* @returns {undefined | AnyNode[]} result
*/
const getPathInAst = (ast, node) => {
if (ast === node) {
return [];
}
const nr = node.range;
const enterNode = n => {
if (!n) return undefined;
const r = n.range;
if (r) {
if (r[0] <= nr[0] && r[1] >= nr[1]) {
const path = getPathInAst(n, node);
if (path) {
path.push(n);
return path;
}
}
}
return undefined;
};
if (Array.isArray(ast)) {
for (let i = 0; i < ast.length; i++) {
const enterResult = enterNode(ast[i]);
if (enterResult !== undefined) return enterResult;
}
} else if (ast && typeof ast === "object") {
const keys = Object.keys(ast);
for (let i = 0; i < keys.length; i++) {
const value = ast[keys[i]];
if (Array.isArray(value)) {
const pathResult = getPathInAst(value, node);
if (pathResult !== undefined) return pathResult;
} else if (value && typeof value === "object") {
const enterResult = enterNode(value);
if (enterResult !== undefined) return enterResult;
}
}
}
};
module.exports = { getAllReferences, getPathInAst };

View File

@@ -15,8 +15,8 @@ const A_CODE = "a".charCodeAt(0);
module.exports = (hash, hashLength) => {
if (hashLength < 1) return "";
const slice = hash.slice(0, hashLength);
if (slice.match(/[^\d]/)) return slice;
if (/[^\d]/.test(slice)) return slice;
return `${String.fromCharCode(
A_CODE + (parseInt(hash[0], 10) % 6)
A_CODE + (Number.parseInt(hash[0], 10) % 6)
)}${slice.slice(1)}`;
};

View File

@@ -77,24 +77,19 @@ function fnv1a64(str) {
*
* We use `numberHash` in `lib/ids/IdHelpers.js` to generate hash values for the module identifier. The generated
* hash is used as a prefix for the module id's to avoid collisions with other modules.
*
* @param {string} str The input string to hash.
* @param {number} range The range of the hash value (0 to range-1).
* @returns {number} - The computed hash value.
*
* @example
*
* ```js
* const numberHash = require("webpack/lib/util/numberHash");
* numberHash("hello", 1000); // 73
* numberHash("hello world"); // 72
* ```
*
*/
module.exports = (str, range) => {
if (range < FNV_64_THRESHOLD) {
return fnv1a32(str) % range;
} else {
return Number(fnv1a64(str) % BigInt(range));
}
return Number(fnv1a64(str) % BigInt(range));
};

View File

@@ -6,7 +6,6 @@
/**
* Convert an object into an ES6 map
*
* @param {object} obj any object type that works with Object.entries()
* @returns {Map<string, any>} an ES6 Map of KV pairs
*/

View File

@@ -5,10 +5,7 @@
"use strict";
const {
SAFE_IDENTIFIER,
RESERVED_IDENTIFIER
} = require("../util/propertyName");
const { SAFE_IDENTIFIER, RESERVED_IDENTIFIER } = require("./propertyName");
/**
* @param {ArrayLike<string>} properties properties
@@ -19,7 +16,7 @@ const propertyAccess = (properties, start = 0) => {
let str = "";
for (let i = start; i < properties.length; i++) {
const p = properties[i];
if (`${+p}` === p) {
if (`${Number(p)}` === p) {
str += `[${p}]`;
} else if (SAFE_IDENTIFIER.test(p) && !RESERVED_IDENTIFIER.has(p)) {
str += `.${p}`;

View File

@@ -64,16 +64,14 @@ const RESERVED_IDENTIFIER = new Set([
* @summary Returns a valid JS property name for the given property.
* Certain strings like "default", "null", and names with whitespace are not
* valid JS property names, so they are returned as strings.
*
* @param {string} prop property name to analyze
* @returns {string} valid JS property name
*/
const propertyName = prop => {
if (SAFE_IDENTIFIER.test(prop) && !RESERVED_IDENTIFIER.has(prop)) {
return prop;
} else {
return JSON.stringify(prop);
}
return JSON.stringify(prop);
};
module.exports = { SAFE_IDENTIFIER, RESERVED_IDENTIFIER, propertyName };

View File

@@ -9,7 +9,7 @@ const { register } = require("./serialization");
const Position = /** @type {TODO} */ (require("acorn")).Position;
const SourceLocation = require("acorn").SourceLocation;
const ValidationError = require("schema-utils/dist/ValidationError").default;
const ValidationError = require("schema-utils").ValidationError;
const {
CachedSource,
ConcatSource,

View File

@@ -19,7 +19,7 @@ const SortableSet = require("./SortableSet");
* @param {EntryOptions=} options optionally already received entry options
* @returns {RuntimeSpec} runtime
*/
exports.getEntryRuntime = (compilation, name, options) => {
module.exports.getEntryRuntime = (compilation, name, options) => {
let dependOn;
let runtime;
if (options) {
@@ -31,7 +31,7 @@ exports.getEntryRuntime = (compilation, name, options) => {
}
if (dependOn) {
/** @type {RuntimeSpec} */
let result = undefined;
let result;
const queue = new Set(dependOn);
for (const name of queue) {
const dep = compilation.entries.get(name);
@@ -46,9 +46,8 @@ exports.getEntryRuntime = (compilation, name, options) => {
}
}
return result || name;
} else {
return runtime || name;
}
return runtime || name;
};
/**
@@ -69,7 +68,7 @@ const forEachRuntime = (runtime, fn, deterministicOrder = false) => {
}
}
};
exports.forEachRuntime = forEachRuntime;
module.exports.forEachRuntime = forEachRuntime;
/**
* @template T
@@ -90,19 +89,19 @@ const getRuntimeKey = runtime => {
if (typeof runtime === "string") return runtime;
return runtime.getFromUnorderedCache(getRuntimesKey);
};
exports.getRuntimeKey = getRuntimeKey;
module.exports.getRuntimeKey = getRuntimeKey;
/**
* @param {string} key key of runtimes
* @returns {RuntimeSpec} runtime(s)
*/
const keyToRuntime = key => {
if (key === "*") return undefined;
if (key === "*") return;
const items = key.split("\n");
if (items.length === 1) return items[0];
return new SortableSet(items);
};
exports.keyToRuntime = keyToRuntime;
module.exports.keyToRuntime = keyToRuntime;
/**
* @template T
@@ -123,13 +122,13 @@ const runtimeToString = runtime => {
if (typeof runtime === "string") return runtime;
return runtime.getFromUnorderedCache(getRuntimesString);
};
exports.runtimeToString = runtimeToString;
module.exports.runtimeToString = runtimeToString;
/**
* @param {RuntimeCondition} runtimeCondition runtime condition
* @returns {string} readable version
*/
exports.runtimeConditionToString = runtimeCondition => {
module.exports.runtimeConditionToString = runtimeCondition => {
if (runtimeCondition === true) return "true";
if (runtimeCondition === false) return "false";
return runtimeToString(runtimeCondition);
@@ -152,40 +151,38 @@ const runtimeEqual = (a, b) => {
return false;
} else if (a.size !== b.size) {
return false;
} else {
a.sort();
b.sort();
const aIt = a[Symbol.iterator]();
const bIt = b[Symbol.iterator]();
for (;;) {
const aV = aIt.next();
if (aV.done) return true;
const bV = bIt.next();
if (aV.value !== bV.value) return false;
}
}
a.sort();
b.sort();
const aIt = a[Symbol.iterator]();
const bIt = b[Symbol.iterator]();
for (;;) {
const aV = aIt.next();
if (aV.done) return true;
const bV = bIt.next();
if (aV.value !== bV.value) return false;
}
};
exports.runtimeEqual = runtimeEqual;
module.exports.runtimeEqual = runtimeEqual;
/**
* @param {RuntimeSpec} a first
* @param {RuntimeSpec} b second
* @returns {-1|0|1} compare
*/
exports.compareRuntime = (a, b) => {
module.exports.compareRuntime = (a, b) => {
if (a === b) {
return 0;
} else if (a === undefined) {
return -1;
} else if (b === undefined) {
return 1;
} else {
const aKey = getRuntimeKey(a);
const bKey = getRuntimeKey(b);
if (aKey < bKey) return -1;
if (aKey > bKey) return 1;
return 0;
}
const aKey = getRuntimeKey(a);
const bKey = getRuntimeKey(b);
if (aKey < bKey) return -1;
if (aKey > bKey) return 1;
return 0;
};
/**
@@ -208,26 +205,23 @@ const mergeRuntime = (a, b) => {
return set;
} else if (b.has(a)) {
return b;
} else {
const set = new SortableSet(b);
set.add(a);
return set;
}
} else {
if (typeof b === "string") {
if (a.has(b)) return a;
const set = new SortableSet(a);
set.add(b);
return set;
} else {
const set = new SortableSet(a);
for (const item of b) set.add(item);
if (set.size === a.size) return a;
return set;
}
const set = new SortableSet(b);
set.add(a);
return set;
}
if (typeof b === "string") {
if (a.has(b)) return a;
const set = new SortableSet(a);
set.add(b);
return set;
}
const set = new SortableSet(a);
for (const item of b) set.add(item);
if (set.size === a.size) return a;
return set;
};
exports.mergeRuntime = mergeRuntime;
module.exports.mergeRuntime = mergeRuntime;
/**
* @param {RuntimeCondition} a first
@@ -235,12 +229,12 @@ exports.mergeRuntime = mergeRuntime;
* @param {RuntimeSpec} runtime full runtime
* @returns {RuntimeCondition} result
*/
exports.mergeRuntimeCondition = (a, b, runtime) => {
module.exports.mergeRuntimeCondition = (a, b, runtime) => {
if (a === false) return b;
if (b === false) return a;
if (a === true || b === true) return true;
const merged = mergeRuntime(a, b);
if (merged === undefined) return undefined;
if (merged === undefined) return;
if (typeof merged === "string") {
if (typeof runtime === "string" && merged === runtime) return true;
return merged;
@@ -256,10 +250,10 @@ exports.mergeRuntimeCondition = (a, b, runtime) => {
* @param {RuntimeSpec} runtime full runtime
* @returns {RuntimeSpec | true} result
*/
exports.mergeRuntimeConditionNonFalse = (a, b, runtime) => {
module.exports.mergeRuntimeConditionNonFalse = (a, b, runtime) => {
if (a === true || b === true) return true;
const merged = mergeRuntime(a, b);
if (merged === undefined) return undefined;
if (merged === undefined) return;
if (typeof merged === "string") {
if (typeof runtime === "string" && merged === runtime) return true;
return merged;
@@ -282,38 +276,34 @@ const mergeRuntimeOwned = (a, b) => {
} else if (a === undefined) {
if (typeof b === "string") {
return b;
} else {
return new SortableSet(b);
}
return new SortableSet(b);
} else if (typeof a === "string") {
if (typeof b === "string") {
const set = new SortableSet();
set.add(a);
set.add(b);
return set;
} else {
const set = new SortableSet(b);
set.add(a);
return set;
}
} else {
if (typeof b === "string") {
a.add(b);
return a;
} else {
for (const item of b) a.add(item);
return a;
}
const set = new SortableSet(b);
set.add(a);
return set;
}
if (typeof b === "string") {
a.add(b);
return a;
}
for (const item of b) a.add(item);
return a;
};
exports.mergeRuntimeOwned = mergeRuntimeOwned;
module.exports.mergeRuntimeOwned = mergeRuntimeOwned;
/**
* @param {RuntimeSpec} a first
* @param {RuntimeSpec} b second
* @returns {RuntimeSpec} merged
*/
exports.intersectRuntime = (a, b) => {
module.exports.intersectRuntime = (a, b) => {
if (a === undefined) {
return b;
} else if (b === undefined) {
@@ -322,26 +312,26 @@ exports.intersectRuntime = (a, b) => {
return a;
} else if (typeof a === "string") {
if (typeof b === "string") {
return undefined;
return;
} else if (b.has(a)) {
return a;
} else {
return undefined;
}
} else {
if (typeof b === "string") {
if (a.has(b)) return b;
return undefined;
} else {
const set = new SortableSet();
for (const item of b) {
if (a.has(item)) set.add(item);
}
if (set.size === 0) return undefined;
if (set.size === 1) for (const item of set) return item;
return set;
}
return;
}
if (typeof b === "string") {
if (a.has(b)) return b;
return;
}
const set = new SortableSet();
for (const item of b) {
if (a.has(item)) set.add(item);
}
if (set.size === 0) return;
if (set.size === 1) {
const [item] = set;
return item;
}
return set;
};
/**
@@ -351,42 +341,42 @@ exports.intersectRuntime = (a, b) => {
*/
const subtractRuntime = (a, b) => {
if (a === undefined) {
return undefined;
return;
} else if (b === undefined) {
return a;
} else if (a === b) {
return undefined;
return;
} else if (typeof a === "string") {
if (typeof b === "string") {
return a;
} else if (b.has(a)) {
return undefined;
} else {
return a;
}
} else {
if (typeof b === "string") {
if (!a.has(b)) return a;
if (a.size === 2) {
for (const item of a) {
if (item !== b) return item;
}
}
const set = new SortableSet(a);
set.delete(b);
return set;
} else {
const set = new SortableSet();
for (const item of a) {
if (!b.has(item)) set.add(item);
}
if (set.size === 0) return undefined;
if (set.size === 1) for (const item of set) return item;
return set;
return;
}
return a;
}
if (typeof b === "string") {
if (!a.has(b)) return a;
if (a.size === 2) {
for (const item of a) {
if (item !== b) return item;
}
}
const set = new SortableSet(a);
set.delete(b);
return set;
}
const set = new SortableSet();
for (const item of a) {
if (!b.has(item)) set.add(item);
}
if (set.size === 0) return;
if (set.size === 1) {
const [item] = set;
return item;
}
return set;
};
exports.subtractRuntime = subtractRuntime;
module.exports.subtractRuntime = subtractRuntime;
/**
* @param {RuntimeCondition} a first
@@ -394,7 +384,7 @@ exports.subtractRuntime = subtractRuntime;
* @param {RuntimeSpec} runtime runtime
* @returns {RuntimeCondition} result
*/
exports.subtractRuntimeCondition = (a, b, runtime) => {
module.exports.subtractRuntimeCondition = (a, b, runtime) => {
if (b === true) return false;
if (b === false) return a;
if (a === false) return false;
@@ -404,15 +394,15 @@ exports.subtractRuntimeCondition = (a, b, runtime) => {
/**
* @param {RuntimeSpec} runtime runtime
* @param {function(RuntimeSpec): boolean} filter filter function
* @param {function(RuntimeSpec=): boolean} filter filter function
* @returns {boolean | RuntimeSpec} true/false if filter is constant for all runtimes, otherwise runtimes that are active
*/
exports.filterRuntime = (runtime, filter) => {
if (runtime === undefined) return filter(undefined);
module.exports.filterRuntime = (runtime, filter) => {
if (runtime === undefined) return filter();
if (typeof runtime === "string") return filter(runtime);
let some = false;
let every = true;
let result = undefined;
let result;
for (const r of runtime) {
const v = filter(r);
if (v) {
@@ -456,7 +446,7 @@ class RuntimeSpecMap {
get(runtime) {
switch (this._mode) {
case 0:
return undefined;
return;
case 1:
return runtimeEqual(this._singleRuntime, runtime)
? this._singleValue
@@ -628,6 +618,9 @@ class RuntimeSpecMap {
}
}
/**
* @returns {IterableIterator<T>} values
*/
values() {
switch (this._mode) {
case 0:
@@ -640,12 +633,15 @@ class RuntimeSpecMap {
}
get size() {
if (/** @type {number} */ (this._mode) <= 1) return this._mode;
if (/** @type {number} */ (this._mode) <= 1) {
return /** @type {number} */ (this._mode);
}
return /** @type {Map<string, T>} */ (this._map).size;
}
}
exports.RuntimeSpecMap = RuntimeSpecMap;
module.exports.RuntimeSpecMap = RuntimeSpecMap;
class RuntimeSpecSet {
/**
@@ -676,6 +672,9 @@ class RuntimeSpecSet {
return this._map.has(getRuntimeKey(runtime));
}
/**
* @returns {IterableIterator<RuntimeSpec>} iterable iterator
*/
[Symbol.iterator]() {
return this._map.values();
}
@@ -685,4 +684,4 @@ class RuntimeSpecSet {
}
}
exports.RuntimeSpecSet = RuntimeSpecSet;
module.exports.RuntimeSpecSet = RuntimeSpecSet;

View File

@@ -6,33 +6,45 @@
"use strict";
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/** @typedef {(string|number|undefined|[])[]} SemVerRange */
/** @typedef {string | number | undefined} SemVerRangeItem */
/** @typedef {(SemVerRangeItem | SemVerRangeItem[])[]} SemVerRange */
/**
* @param {string} str version string
* @returns {(string|number|undefined|[])[]} parsed version
* @returns {SemVerRange} parsed version
*/
const parseVersion = str => {
/**
* @param {str} str str
* @returns {(string | number)[]} result
*/
var splitAndConvert = function (str) {
return str.split(".").map(function (item) {
// eslint-disable-next-line eqeqeq
return +item == item ? +item : item;
return +item == /** @type {EXPECTED_ANY} */ (item) ? +item : item;
});
};
var match = /^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str);
/** @type {(string|number|undefined|[])[]} */
var match =
/** @type {RegExpExecArray} */
(/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str));
/** @type {(string | number | undefined | [])[]} */
var ver = match[1] ? splitAndConvert(match[1]) : [];
if (match[2]) {
ver.length++;
ver.push.apply(ver, splitAndConvert(match[2]));
}
if (match[3]) {
ver.push([]);
ver.push.apply(ver, splitAndConvert(match[3]));
}
return ver;
};
exports.parseVersion = parseVersion;
module.exports.parseVersion = parseVersion;
/* eslint-disable eqeqeq */
/**
@@ -82,23 +94,35 @@ const versionLt = (a, b) => {
}
};
/* eslint-enable eqeqeq */
exports.versionLt = versionLt;
module.exports.versionLt = versionLt;
/**
* @param {string} str range string
* @returns {SemVerRange} parsed range
*/
exports.parseRange = str => {
module.exports.parseRange = str => {
/**
* @param {string} str str
* @returns {(string | number)[]} result
*/
const splitAndConvert = str => {
return str
.split(".")
.map(item => (item !== "NaN" && `${+item}` === item ? +item : item));
};
// see https://docs.npmjs.com/misc/semver#range-grammar for grammar
/**
* @param {string} str str
* @returns {SemVerRangeItem[]}
*/
const parsePartial = str => {
const match = /^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str);
/** @type {(string|number|undefined|[])[]} */
const match =
/** @type {RegExpExecArray} */
(/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str));
/** @type {SemVerRangeItem[]} */
const ver = match[1] ? [0, ...splitAndConvert(match[1])] : [0];
if (match[2]) {
ver.length++;
ver.push.apply(ver, splitAndConvert(match[2]));
@@ -116,6 +140,12 @@ exports.parseRange = str => {
return ver;
};
/**
*
* @param {SemVerRangeItem[]} range range
* @returns {SemVerRangeItem[]}
*/
const toFixed = range => {
if (range.length === 1) {
// Special case for "*" is "x.x.x" instead of "="
@@ -126,13 +156,24 @@ exports.parseRange = str => {
} else if (range.length === 3) {
// Special case for "1.2" is "1.2.x" instead of "=1.2"
return [2, ...range.slice(1)];
} else {
return [range.length, ...range.slice(1)];
}
return [range.length, ...range.slice(1)];
};
/**
*
* @param {SemVerRangeItem[]} range
* @returns {SemVerRangeItem[]} result
*/
const negate = range => {
return [-range[0] - 1, ...range.slice(1)];
return [-(/** @type { [number]} */ (range)[0]) - 1, ...range.slice(1)];
};
/**
* @param {string} str str
* @returns {SemVerRange}
*/
const parseSimple = str => {
// simple ::= primitive | partial | tilde | caret
// primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | '!' ) ( ' ' ) * partial
@@ -143,6 +184,7 @@ exports.parseRange = str => {
const remainder = parsePartial(
start.length ? str.slice(start.length).trim() : str.trim()
);
switch (start) {
case "^":
if (remainder.length > 1 && remainder[1] === 0) {
@@ -185,6 +227,13 @@ exports.parseRange = str => {
throw new Error("Unexpected start value");
}
};
/**
*
* @param {SemVerRangeItem[][]} items items
* @param {number} fn fn
* @returns {SemVerRange} result
*/
const combine = (items, fn) => {
if (items.length === 1) return items[0];
const arr = [];
@@ -195,38 +244,64 @@ exports.parseRange = str => {
arr.push(...item.slice(1));
}
}
// eslint-disable-next-line no-sparse-arrays
return [, ...arr, ...items.slice(1).map(() => fn)];
};
/**
* @param {string} str str
* @returns {SemVerRange}
*/
const parseRange = str => {
// range ::= hyphen | simple ( ' ' ( ' ' ) * simple ) * | ''
// hyphen ::= partial ( ' ' ) * ' - ' ( ' ' ) * partial
const items = str.split(/\s+-\s+/);
if (items.length === 1) {
const items = str
.trim()
.split(/(?<=[-0-9A-Za-z])\s+/g)
.map(parseSimple);
const items =
/** @type {SemVerRangeItem[][]} */
(
str
.trim()
.split(/(?<=[-0-9A-Za-z])\s+/g)
.map(parseSimple)
);
return combine(items, 2);
}
const a = parsePartial(items[0]);
const b = parsePartial(items[1]);
// >=a <=b => and( >=a, or( <b, =b ) ) => >=a, <b, =b, or, and
// eslint-disable-next-line no-sparse-arrays
return [, toFixed(b), negate(b), 1, a, 2];
};
/**
* @param {string} str str
* @returns {SemVerRange}
*/
const parseLogicalOr = str => {
// range-set ::= range ( logical-or range ) *
// logical-or ::= ( ' ' ) * '||' ( ' ' ) *
const items = str.split(/\s*\|\|\s*/).map(parseRange);
const items =
/** @type {SemVerRangeItem[][]} */
(str.split(/\s*\|\|\s*/).map(parseRange));
return combine(items, 1);
};
return parseLogicalOr(str);
};
/* eslint-disable eqeqeq */
/**
* @param {SemVerRange} range
* @returns {string}
*/
const rangeToString = range => {
var fixCount = range[0];
var fixCount = /** @type {number} */ (range[0]);
var str = "";
if (range.length === 1) {
return "*";
@@ -256,32 +331,32 @@ const rangeToString = range => {
(needDot > 0 ? "." : "") + ((needDot = 2), item);
}
return str;
} else {
var stack = [];
// eslint-disable-next-line no-redeclare
for (var i = 1; i < range.length; i++) {
// eslint-disable-next-line no-redeclare
var item = range[i];
stack.push(
item === 0
? "not(" + pop() + ")"
: item === 1
? "(" + pop() + " || " + pop() + ")"
: item === 2
? stack.pop() + " " + stack.pop()
: rangeToString(item)
);
}
return pop();
}
/** @type {string[]} */
var stack = [];
// eslint-disable-next-line no-redeclare
for (var i = 1; i < range.length; i++) {
// eslint-disable-next-line no-redeclare
var item = range[i];
stack.push(
item === 0
? "not(" + pop() + ")"
: item === 1
? "(" + pop() + " || " + pop() + ")"
: item === 2
? stack.pop() + " " + stack.pop()
: rangeToString(/** @type {SemVerRange} */ (item))
);
}
return pop();
function pop() {
return stack.pop().replace(/^\((.+)\)$/, "$1");
return /** @type {string} */ (stack.pop()).replace(/^\((.+)\)$/, "$1");
}
};
/* eslint-enable eqeqeq */
exports.rangeToString = rangeToString;
/* eslint-disable eqeqeq */
module.exports.rangeToString = rangeToString;
/**
* @param {SemVerRange} range version range
* @param {string} version the version
@@ -340,16 +415,22 @@ const satisfy = (range, version) => {
// big-cmp: when negated => return false, else => next-nequ
// small-cmp: when negated => next-nequ, else => return false
var rangeType = j < range.length ? (typeof range[j])[0] : "";
var rangeType =
/** @type {"s" | "n" | "u" | ""} */
(j < range.length ? (typeof range[j])[0] : "");
/** @type {number | string | undefined} */
var versionValue;
/** @type {"n" | "s" | "u" | "o" | undefined} */
var versionType;
// Handles first column in both tables (end of version or object)
if (
i >= version.length ||
((versionValue = version[i]),
(versionType = (typeof versionValue)[0]) == "o")
(versionType = /** @type {"n" | "s" | "u" | "o"} */ (
(typeof versionValue)[0]
)) == "o")
) {
// Handles nequal
if (!isEqual) return true;
@@ -377,7 +458,11 @@ const satisfy = (range, version) => {
}
} else {
// Handles "cmp" cases
if (negated ? versionValue > range[j] : versionValue < range[j]) {
if (
negated
? versionValue > /** @type {(number | string)[]} */ (range)[j]
: versionValue < /** @type {(number | string)[]} */ (range)[j]
) {
return false;
}
if (versionValue != range[j]) isEqual = false;
@@ -399,6 +484,7 @@ const satisfy = (range, version) => {
}
} else {
// Handles all "next-ver" cases in the second table
// eslint-disable-next-line no-lonely-if
if (rangeType != "s" && rangeType != "n") {
isEqual = false;
j--;
@@ -408,17 +494,20 @@ const satisfy = (range, version) => {
}
}
}
/** @type {(boolean | number)[]} */
var stack = [];
var p = stack.pop.bind(stack);
// eslint-disable-next-line no-redeclare
for (var i = 1; i < range.length; i++) {
var item = /** @type {SemVerRange | 0 | 1 | 2} */ (range[i]);
var item = /** @type {SemVerRangeItem[] | 0 | 1 | 2} */ (range[i]);
stack.push(
item == 1
? p() | p()
? /** @type {() => number} */ (p)() | /** @type {() => number} */ (p)()
: item == 2
? p() & p()
? /** @type {() => number} */ (p)() &
/** @type {() => number} */ (p)()
: item
? satisfy(item, version)
: !p()
@@ -427,9 +516,13 @@ const satisfy = (range, version) => {
return !!p();
};
/* eslint-enable eqeqeq */
exports.satisfy = satisfy;
module.exports.satisfy = satisfy;
exports.stringifyHoley = json => {
/**
* @param {SemVerRange | string | number | false | undefined} json
* @returns {string}
*/
module.exports.stringifyHoley = json => {
switch (typeof json) {
case "undefined":
return "";
@@ -442,15 +535,19 @@ exports.stringifyHoley = json => {
}
str += "]";
return str;
} else {
return JSON.stringify(json);
}
return JSON.stringify(json);
default:
return JSON.stringify(json);
}
};
//#region runtime code: parseVersion
/**
* @param {RuntimeTemplate} runtimeTemplate
* @returns {string}
*/
exports.parseVersionRuntimeCode = runtimeTemplate =>
`var parseVersion = ${runtimeTemplate.basicFunction("str", [
"// see webpack/lib/util/semver.js for original code",
@@ -459,6 +556,10 @@ exports.parseVersionRuntimeCode = runtimeTemplate =>
//#endregion
//#region runtime code: versionLt
/**
* @param {RuntimeTemplate} runtimeTemplate
* @returns {string}
*/
exports.versionLtRuntimeCode = runtimeTemplate =>
`var versionLt = ${runtimeTemplate.basicFunction("a, b", [
"// see webpack/lib/util/semver.js for original code",
@@ -467,6 +568,10 @@ exports.versionLtRuntimeCode = runtimeTemplate =>
//#endregion
//#region runtime code: rangeToString
/**
* @param {RuntimeTemplate} runtimeTemplate
* @returns {string}
*/
exports.rangeToStringRuntimeCode = runtimeTemplate =>
`var rangeToString = ${runtimeTemplate.basicFunction("range", [
"// see webpack/lib/util/semver.js for original code",
@@ -475,6 +580,10 @@ exports.rangeToStringRuntimeCode = runtimeTemplate =>
//#endregion
//#region runtime code: satisfy
/**
* @param {RuntimeTemplate} runtimeTemplate
* @returns {string}
*/
exports.satisfyRuntimeCode = runtimeTemplate =>
`var satisfy = ${runtimeTemplate.basicFunction("range, version", [
"// see webpack/lib/util/semver.js for original code",

View File

@@ -39,7 +39,11 @@ const registerSerializers = memoize(() => {
// This allows bundling all internal serializers
const internalSerializables = require("./internalSerializables");
getObjectMiddleware().registerLoader(/^webpack\/lib\//, req => {
const loader = internalSerializables[req.slice("webpack/lib/".length)];
const loader =
internalSerializables[
/** @type {keyof import("./internalSerializables")} */
(req.slice("webpack/lib/".length))
];
if (loader) {
loader();
} else {
@@ -88,6 +92,9 @@ module.exports = {
new SingleItemMiddleware(),
new (getObjectMiddleware())(context => {
if (context.write) {
/**
* @param {any} value value
*/
context.writeLazy = value => {
context.write(
SerializerMiddleware.createLazy(value, binaryMiddleware)
@@ -115,11 +122,19 @@ module.exports = {
new SingleItemMiddleware(),
new (getObjectMiddleware())(context => {
if (context.write) {
/**
* @param {any} value value
*/
context.writeLazy = value => {
context.write(
SerializerMiddleware.createLazy(value, binaryMiddleware)
);
};
/**
* @param {any} value value
* @param {object=} options lazy options
* @returns {function(): Promise<any> | any} lazy function
*/
context.writeSeparate = (value, options) => {
const lazy = SerializerMiddleware.createLazy(
value,

View File

@@ -16,7 +16,7 @@
* @template T
* @template R
* @typedef {object} GroupConfig
* @property {function(T): string[]} getKeys
* @property {function(T): string[] | undefined} getKeys
* @property {function(string, (R | T)[], T[]): R} createGroup
* @property {function(string, T[]): GroupOptions=} getOptions
*/
@@ -111,10 +111,10 @@ const smartGrouping = (items, groupConfigs) => {
const results = [];
for (;;) {
/** @type {Group<T, R> | undefined} */
let bestGroup = undefined;
let bestGroup;
let bestGroupSize = -1;
let bestGroupItems = undefined;
let bestGroupOptions = undefined;
let bestGroupItems;
let bestGroupOptions;
for (const [group, state] of groupMap) {
const { items, used } = state;
let options = state.options;
@@ -138,7 +138,7 @@ const smartGrouping = (items, groupConfigs) => {
}
}
const targetGroupCount = (options && options.targetGroupCount) || 4;
let sizeValue = force
const sizeValue = force
? items.size
: Math.min(
items.size,

View File

@@ -58,4 +58,4 @@ const isSourceEqual = (a, b) => {
}
return result;
};
exports.isSourceEqual = isSourceEqual;
module.exports.isSourceEqual = isSourceEqual;