Merge pull request #9391 from vankop/create-hash-typescript

esdoc(createHash)
This commit is contained in:
Tobias Koppers 2019-07-15 17:26:21 +02:00 committed by GitHub
commit 0beeb7e30a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 145 additions and 23 deletions

View File

@ -71,7 +71,8 @@ module.exports = {
};
return acc;
}, {})),
extends: "extends"
extends: "extends",
constructor: "constructor"
}
}
},

View File

@ -1094,7 +1094,7 @@ export interface OutputOptions {
/**
* Algorithm used for generation the hash (see node.js crypto package)
*/
hashFunction?: string | (new () => import("../lib/util/createHash").Hash);
hashFunction?: string | import("../lib/util/createHash").HashConstructor;
/**
* Any string which is added to the hash to salt it
*/

View File

@ -0,0 +1,43 @@
"use strict";
const WebpackError = require("./WebpackError");
const CURRENT_METHOD_REGEXP = /at ([a-zA-Z0-9_.]*)/;
/**
* @param {string=} method method name
* @returns {string} message
*/
function createMessage(method) {
return `Abstract method${method ? " " + method : ""}. Must be overridden.`;
}
/**
* @constructor
*/
function Message() {
this.stack = undefined;
Error.captureStackTrace(this);
/** @type {RegExpMatchArray} */
const match = this.stack.split("\n")[3].match(CURRENT_METHOD_REGEXP);
this.message = match && match[1] ? createMessage(match[1]) : createMessage();
}
/**
* Error for abstract method
* @example
* class FooClass {
* abstractMethod() {
* throw new AbstractMethodError(); // error message: Abstract method FooClass.abstractMethod. Must be overriden.
* }
* }
*
*/
class AbstractMethodError extends WebpackError {
constructor() {
super(new Message().message);
this.name = "AbstractMethodError";
}
}
module.exports = AbstractMethodError;

View File

@ -2294,7 +2294,7 @@ class Compilation extends Tapable {
const module = modules[i];
const moduleHash = createHash(hashFunction);
module.updateHash(moduleHash);
module.hash = moduleHash.digest(hashDigest);
module.hash = /** @type {string} */ (moduleHash.digest(hashDigest));
module.renderedHash = module.hash.substr(0, hashDigestLength);
}
// clone needed as sort below is inplace mutation
@ -2329,7 +2329,7 @@ class Compilation extends Tapable {
this.dependencyTemplates
);
this.hooks.chunkHash.call(chunk, chunkHash);
chunk.hash = chunkHash.digest(hashDigest);
chunk.hash = /** @type {string} */ (chunkHash.digest(hashDigest));
hash.update(chunk.hash);
chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
this.hooks.contentHash.call(chunk);
@ -2337,7 +2337,7 @@ class Compilation extends Tapable {
this.errors.push(new ChunkRenderError(chunk, "", err));
}
}
this.fullHash = hash.digest(hashDigest);
this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
this.hash = this.fullHash.substr(0, hashDigestLength);
}
@ -2353,7 +2353,7 @@ class Compilation extends Tapable {
const hash = createHash(hashFunction);
hash.update(this.fullHash);
hash.update(update);
this.fullHash = hash.digest(hashDigest);
this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
this.hash = this.fullHash.substr(0, hashDigestLength);
}

View File

@ -45,7 +45,9 @@ class HashedModuleIdsPlugin {
});
const hash = createHash(options.hashFunction);
hash.update(id);
const hashId = hash.digest(options.hashDigest);
const hashId = /** @type {string} */ (hash.digest(
options.hashDigest
));
let len = options.hashDigestLength;
while (usedIds.has(hashId.substr(0, len))) len++;
module.id = hashId.substr(0, len);

View File

@ -148,9 +148,8 @@ class JavascriptModulesPlugin {
hash.update(m.hash);
}
}
chunk.contentHash.javascript = hash
.digest(hashDigest)
.substr(0, hashDigestLength);
const digest = /** @type {string} */ (hash.digest(hashDigest));
chunk.contentHash.javascript = digest.substr(0, hashDigestLength);
});
}
);

View File

@ -44,7 +44,8 @@ const getBefore = (str, token) => {
const getHash = str => {
const hash = createHash("md4");
hash.update(str);
return hash.digest("hex").substr(0, 4);
const digest = /** @type {string} */ (hash.digest("hex"));
return digest.substr(0, 4);
};
const asRegExp = test => {

View File

@ -10,7 +10,8 @@ const RequestShortener = require("./RequestShortener");
const getHash = str => {
const hash = createHash("md4");
hash.update(str);
return hash.digest("hex").substr(0, 4);
const digest = /** @type {string} */ (hash.digest("hex"));
return digest.substr(0, 4);
};
class NamedModulesPlugin {

View File

@ -405,7 +405,7 @@ class NormalModule extends Module {
}
hash.update("meta");
hash.update(JSON.stringify(this.buildMeta));
this._buildHash = hash.digest("hex");
this._buildHash = /** @type {string} */ (hash.digest("hex"));
}
build(options, compilation, resolver, fs, callback) {

View File

@ -4,21 +4,50 @@
*/
"use strict";
/** @typedef {{new(): Hash}} HashConstructor */
/**
* @typedef {Object} Hash
* @property {function(string|Buffer, string=): Hash} update
* @property {function(string): string} digest
*/
const AbstractMethodError = require("../AbstractMethodError");
const BULK_SIZE = 1000;
class BulkUpdateDecorator {
class Hash {
/**
* Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
* @param {string|Buffer} data data
* @param {string=} inputEncoding data encoding
* @returns {this} updated hash
*/
update(data, inputEncoding) {
throw new AbstractMethodError();
}
/**
* Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
* @param {string=} encoding encoding of the return value
* @returns {string|Buffer} digest
*/
digest(encoding) {
throw new AbstractMethodError();
}
}
exports.Hash = Hash;
/** @typedef {typeof Hash} HashConstructor */
class BulkUpdateDecorator extends Hash {
/**
* @param {Hash} hash hash
*/
constructor(hash) {
super();
this.hash = hash;
this.buffer = "";
}
/**
* Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
* @param {string|Buffer} data data
* @param {string=} inputEncoding data encoding
* @returns {this} updated hash
*/
update(data, inputEncoding) {
if (
inputEncoding !== undefined ||
@ -40,6 +69,11 @@ class BulkUpdateDecorator {
return this;
}
/**
* Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
* @param {string=} encoding encoding of the return value
* @returns {string|Buffer} digest
*/
digest(encoding) {
if (this.buffer.length > 0) {
this.hash.update(this.buffer);
@ -51,18 +85,32 @@ class BulkUpdateDecorator {
}
}
/* istanbul ignore next */
class DebugHash {
/**
* 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}
* @param {string|Buffer} data data
* @param {string=} inputEncoding data encoding
* @returns {this} updated hash
*/
update(data, inputEncoding) {
if (typeof data !== "string") data = data.toString("utf-8");
this.string += data;
return this;
}
/**
* Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
* @param {string=} encoding encoding of the return value
* @returns {string|Buffer} digest
*/
digest(encoding) {
return this.string.replace(/[^a-z0-9]+/gi, m =>
Buffer.from(m).toString("hex")

View File

@ -905,7 +905,7 @@
},
{
"instanceof": "Function",
"tsType": "(new () => import('../lib/util/createHash').Hash)"
"tsType": "import('../lib/util/createHash').HashConstructor"
}
]
},

View File

@ -0,0 +1,27 @@
"use strict";
const AbstractMethodError = require("../lib/AbstractMethodError");
describe("WebpackError", () => {
class Foo {
abstractMethod() {
return new AbstractMethodError();
}
}
class Child extends Foo {}
const expectedMessage = "Abstract method $1. Must be overridden.";
it("Should construct message with caller info", () => {
const fooClassError = new Foo().abstractMethod();
const childClassError = new Child().abstractMethod();
expect(fooClassError.message).toBe(
expectedMessage.replace("$1", "Foo.abstractMethod")
);
expect(childClassError.message).toBe(
expectedMessage.replace("$1", "Child.abstractMethod")
);
});
});