WXL
3 天以前 9bce51f651aad297ef9eb6df832bfdaf1de05d84
node_modules/webpack/lib/util/createHash.js
@@ -5,203 +5,8 @@
"use strict";
const Hash = require("./Hash");
/** @typedef {import("../../declarations/WebpackOptions").HashDigest} Encoding */
/** @typedef {import("./Hash")} Hash */
/** @typedef {import("../../declarations/WebpackOptions").HashFunction} HashFunction */
const BULK_SIZE = 3;
// We are using an object instead of a Map as this will stay static during the runtime
// so access to it can be optimized by v8
/** @type {{[key: string]: Map<string, string>}} */
const digestCaches = {};
/** @typedef {() => Hash} HashFactory */
class BulkUpdateDecorator extends Hash {
   /**
    * @param {Hash | HashFactory} hashOrFactory function to create a hash
    * @param {string=} hashKey key for caching
    */
   constructor(hashOrFactory, hashKey) {
      super();
      this.hashKey = hashKey;
      if (typeof hashOrFactory === "function") {
         this.hashFactory = hashOrFactory;
         this.hash = undefined;
      } else {
         this.hashFactory = undefined;
         this.hash = hashOrFactory;
      }
      this.buffer = "";
   }
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @overload
    * @param {string | Buffer} data data
    * @returns {Hash} updated hash
    */
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @overload
    * @param {string} data data
    * @param {Encoding} inputEncoding data encoding
    * @returns {Hash} updated hash
    */
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @param {string | Buffer} data data
    * @param {Encoding=} inputEncoding data encoding
    * @returns {Hash} updated hash
    */
   update(data, inputEncoding) {
      if (
         inputEncoding !== undefined ||
         typeof data !== "string" ||
         data.length > BULK_SIZE
      ) {
         if (this.hash === undefined) {
            this.hash = /** @type {HashFactory} */ (this.hashFactory)();
         }
         if (this.buffer.length > 0) {
            this.hash.update(this.buffer);
            this.buffer = "";
         }
         if (typeof data === "string" && inputEncoding) {
            this.hash.update(data, inputEncoding);
         } else {
            this.hash.update(data);
         }
      } else {
         this.buffer += data;
         if (this.buffer.length > BULK_SIZE) {
            if (this.hash === undefined) {
               this.hash = /** @type {HashFactory} */ (this.hashFactory)();
            }
            this.hash.update(this.buffer);
            this.buffer = "";
         }
      }
      return this;
   }
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @overload
    * @returns {Buffer} digest
    */
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @overload
    * @param {Encoding} encoding encoding of the return value
    * @returns {string} digest
    */
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @param {Encoding=} encoding encoding of the return value
    * @returns {string | Buffer} digest
    */
   digest(encoding) {
      let digestCache;
      const buffer = this.buffer;
      if (this.hash === undefined) {
         // short data for hash, we can use caching
         const cacheKey = `${this.hashKey}-${encoding}`;
         digestCache = digestCaches[cacheKey];
         if (digestCache === undefined) {
            digestCache = digestCaches[cacheKey] = new Map();
         }
         const cacheEntry = digestCache.get(buffer);
         if (cacheEntry !== undefined) return cacheEntry;
         this.hash = /** @type {HashFactory} */ (this.hashFactory)();
      }
      if (buffer.length > 0) {
         this.hash.update(buffer);
      }
      if (!encoding) {
         const result = this.hash.digest();
         if (digestCache !== undefined) {
            digestCache.set(buffer, result);
         }
         return result;
      }
      const digestResult = this.hash.digest(encoding);
      // Compatibility with the old hash library
      const result =
         typeof digestResult === "string"
            ? digestResult
            : /** @type {NodeJS.TypedArray} */ (digestResult).toString();
      if (digestCache !== undefined) {
         digestCache.set(buffer, result);
      }
      return result;
   }
}
/* istanbul ignore next */
class DebugHash extends Hash {
   constructor() {
      super();
      this.string = "";
   }
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @overload
    * @param {string | Buffer} data data
    * @returns {Hash} updated hash
    */
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @overload
    * @param {string} data data
    * @param {Encoding} inputEncoding data encoding
    * @returns {Hash} updated hash
    */
   /**
    * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
    * @param {string | Buffer} data data
    * @param {Encoding=} inputEncoding data encoding
    * @returns {Hash} updated hash
    */
   update(data, inputEncoding) {
      if (typeof data !== "string") data = data.toString("utf8");
      const prefix = Buffer.from("@webpack-debug-digest@").toString("hex");
      if (data.startsWith(prefix)) {
         data = Buffer.from(data.slice(prefix.length), "hex").toString();
      }
      this.string += `[${data}](${
         /** @type {string} */
         (
            // eslint-disable-next-line unicorn/error-message
            new Error().stack
         ).split("\n", 3)[2]
      })\n`;
      return this;
   }
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @overload
    * @returns {Buffer} digest
    */
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @overload
    * @param {Encoding} encoding encoding of the return value
    * @returns {string} digest
    */
   /**
    * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
    * @param {Encoding=} encoding encoding of the return value
    * @returns {string | Buffer} digest
    */
   digest(encoding) {
      return Buffer.from(`@webpack-debug-digest@${this.string}`).toString("hex");
   }
}
/** @type {typeof import("crypto") | undefined} */
let crypto;
@@ -209,8 +14,12 @@
let createXXHash64;
/** @type {typeof import("./hash/md4") | undefined} */
let createMd4;
/** @type {typeof import("./hash/DebugHash") | undefined} */
let DebugHash;
/** @type {typeof import("./hash/BatchedHash") | undefined} */
let BatchedHash;
/** @type {typeof import("./hash/BulkUpdateHash") | undefined} */
let BulkUpdateHash;
/**
 * Creates a hash by name or function
@@ -219,12 +28,18 @@
 */
module.exports = (algorithm) => {
   if (typeof algorithm === "function") {
      if (BulkUpdateHash === undefined) {
         BulkUpdateHash = require("./hash/BulkUpdateHash");
      }
      // eslint-disable-next-line new-cap
      return new BulkUpdateDecorator(() => new algorithm());
      return new BulkUpdateHash(() => new algorithm());
   }
   switch (algorithm) {
      // TODO add non-cryptographic algorithm here
      case "debug":
         if (DebugHash === undefined) {
            DebugHash = require("./hash/DebugHash");
         }
         return new DebugHash();
      case "xxhash64":
         if (createXXHash64 === undefined) {
@@ -248,7 +63,10 @@
         )(createMd4());
      case "native-md4":
         if (crypto === undefined) crypto = require("crypto");
         return new BulkUpdateDecorator(
         if (BulkUpdateHash === undefined) {
            BulkUpdateHash = require("./hash/BulkUpdateHash");
         }
         return new BulkUpdateHash(
            () =>
               /** @type {Hash} */ (
                  /** @type {typeof import("crypto")} */
@@ -258,7 +76,10 @@
         );
      default:
         if (crypto === undefined) crypto = require("crypto");
         return new BulkUpdateDecorator(
         if (BulkUpdateHash === undefined) {
            BulkUpdateHash = require("./hash/BulkUpdateHash");
         }
         return new BulkUpdateHash(
            () =>
               /** @type {Hash} */ (
                  /** @type {typeof import("crypto")} */