-
-
Notifications
You must be signed in to change notification settings - Fork 27
/
index.js
66 lines (50 loc) · 1.73 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import {Worker} from 'node:worker_threads';
import crypto from 'node:crypto';
import {bufferToHex} from './utilities.js';
let create = algorithm => async (buffer, {outputFormat = 'hex'} = {}) => {
const hash = crypto.createHash(algorithm);
hash.update(buffer, typeof buffer === 'string' ? 'utf8' : undefined);
if (outputFormat === 'hex') {
return hash.digest('hex');
}
return hash.digest().buffer;
};
if (Worker !== undefined) {
const threadFilePath = new URL('thread.js', import.meta.url);
let worker; // Lazy
let taskIdCounter = 0;
const tasks = new Map();
const createWorker = () => {
worker = new Worker(threadFilePath);
worker.on('message', message => {
const task = tasks.get(message.id);
tasks.delete(message.id);
if (tasks.size === 0) {
worker.unref();
}
task(message.value);
});
worker.on('error', error => {
// Any error here is effectively an equivalent of segfault and have no scope, so we just throw it on callback level
throw error;
});
};
const taskWorker = (value, transferList) => new Promise(resolve => {
const id = taskIdCounter++;
tasks.set(id, resolve);
if (worker === undefined) {
createWorker();
}
worker.ref();
worker.postMessage({id, value}, transferList);
});
create = algorithm => async (source, {outputFormat = 'hex'} = {}) => {
const {buffer} = typeof source === 'string' ? new TextEncoder().encode(source) : (source instanceof ArrayBuffer ? new Uint8Array(source) : source);
const hash = await taskWorker({algorithm, buffer}, [buffer]);
return outputFormat === 'hex' ? bufferToHex(hash) : hash;
};
}
export const sha1 = create('sha1');
export const sha256 = create('sha256');
export const sha384 = create('sha384');
export const sha512 = create('sha512');