summaryrefslogtreecommitdiff
path: root/node_modules/watchpack/lib/reducePlan.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-11-05 17:16:09 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-11-05 17:16:09 +0800
commitd1d9f00b1bd660842addf5e6b1d1b64c852a9eea (patch)
tree60fb37ae73a1109d95301de5ec9b61b5726a4b61 /node_modules/watchpack/lib/reducePlan.js
parent7c85166c4cbdd862fc4252007d2df5befcbc2a58 (diff)
added hover prefixer
Diffstat (limited to 'node_modules/watchpack/lib/reducePlan.js')
-rw-r--r--node_modules/watchpack/lib/reducePlan.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/node_modules/watchpack/lib/reducePlan.js b/node_modules/watchpack/lib/reducePlan.js
new file mode 100644
index 00000000..b281ed69
--- /dev/null
+++ b/node_modules/watchpack/lib/reducePlan.js
@@ -0,0 +1,138 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+const path = require("path");
+
+/**
+ * @template T
+ * @typedef {Object} TreeNode
+ * @property {string} filePath
+ * @property {TreeNode} parent
+ * @property {TreeNode[]} children
+ * @property {number} entries
+ * @property {boolean} active
+ * @property {T[] | T | undefined} value
+ */
+
+/**
+ * @template T
+ * @param {Map<string, T[] | T} plan
+ * @param {number} limit
+ * @returns {Map<string, Map<T, string>>} the new plan
+ */
+module.exports = (plan, limit) => {
+ const treeMap = new Map();
+ // Convert to tree
+ for (const [filePath, value] of plan) {
+ treeMap.set(filePath, {
+ filePath,
+ parent: undefined,
+ children: undefined,
+ entries: 1,
+ active: true,
+ value
+ });
+ }
+ let currentCount = treeMap.size;
+ // Create parents and calculate sum of entries
+ for (const node of treeMap.values()) {
+ const parentPath = path.dirname(node.filePath);
+ if (parentPath !== node.filePath) {
+ let parent = treeMap.get(parentPath);
+ if (parent === undefined) {
+ parent = {
+ filePath: parentPath,
+ parent: undefined,
+ children: [node],
+ entries: node.entries,
+ active: false,
+ value: undefined
+ };
+ treeMap.set(parentPath, parent);
+ node.parent = parent;
+ } else {
+ node.parent = parent;
+ if (parent.children === undefined) {
+ parent.children = [node];
+ } else {
+ parent.children.push(node);
+ }
+ do {
+ parent.entries += node.entries;
+ parent = parent.parent;
+ } while (parent);
+ }
+ }
+ }
+ // Reduce until limit reached
+ while (currentCount > limit) {
+ // Select node that helps reaching the limit most effectively without overmerging
+ const overLimit = currentCount - limit;
+ let bestNode = undefined;
+ let bestCost = Infinity;
+ for (const node of treeMap.values()) {
+ if (node.entries <= 1 || !node.children || !node.parent) continue;
+ if (node.children.length === 0) continue;
+ if (node.children.length === 1 && !node.value) continue;
+ // Try to select the node with has just a bit more entries than we need to reduce
+ // When just a bit more is over 30% over the limit,
+ // also consider just a bit less entries then we need to reduce
+ const cost =
+ node.entries - 1 >= overLimit
+ ? node.entries - 1 - overLimit
+ : overLimit - node.entries + 1 + limit * 0.3;
+ if (cost < bestCost) {
+ bestNode = node;
+ bestCost = cost;
+ }
+ }
+ if (!bestNode) break;
+ // Merge all children
+ const reduction = bestNode.entries - 1;
+ bestNode.active = true;
+ bestNode.entries = 1;
+ currentCount -= reduction;
+ let parent = bestNode.parent;
+ while (parent) {
+ parent.entries -= reduction;
+ parent = parent.parent;
+ }
+ const queue = new Set(bestNode.children);
+ for (const node of queue) {
+ node.active = false;
+ node.entries = 0;
+ if (node.children) {
+ for (const child of node.children) queue.add(child);
+ }
+ }
+ }
+ // Write down new plan
+ const newPlan = new Map();
+ for (const rootNode of treeMap.values()) {
+ if (!rootNode.active) continue;
+ const map = new Map();
+ const queue = new Set([rootNode]);
+ for (const node of queue) {
+ if (node.active && node !== rootNode) continue;
+ if (node.value) {
+ if (Array.isArray(node.value)) {
+ for (const item of node.value) {
+ map.set(item, node.filePath);
+ }
+ } else {
+ map.set(node.value, node.filePath);
+ }
+ }
+ if (node.children) {
+ for (const child of node.children) {
+ queue.add(child);
+ }
+ }
+ }
+ newPlan.set(rootNode.filePath, map);
+ }
+ return newPlan;
+};