### Added

- Add dedicated ESM, CommonJS, Node.js, and browser distribution entry points.
- Add streaming support to the native Node.js SHA-256, SHA-224, and HMAC implementations.
- Add distribution contract tests and real browser Web Worker tests with Playwright.
- Add Node.js 16, 18, 20, 22, and 24 runtime tests against the packed npm artifact.

### Changed
- Refactor the implementation into environment-independent core and Node.js modules.
- Use the native Node.js `crypto` implementation for hashing and HMAC.
- Load the package version automatically when generating distribution banners.
- Export unminified ESM source directly and build only CommonJS and browser/minified distributions.
- Replace `expect.js`, NYC, Tiny Worker, and UglifyJS with Node.js assert, c8, Playwright, and Rollup/Terser.
- Build automatically before `npm pack` and `npm publish`.
- Throw error if update after finalize

### Removed
- Remove runtime CommonJS, AMD, Node.js, Web Worker, and ArrayBuffer environment switches from the core implementation.
- Remove legacy environment flags and obsolete compatibility polyfills.
- Remove the old generated `sha256.mjs` and `sha256.node.mjs` entry points.
This commit is contained in:
Yi-Cyuan Chen
2026-07-27 14:30:34 +08:00
parent b766562f6a
commit a6d0f636aa
40 changed files with 1910 additions and 3363 deletions
+87
View File
@@ -0,0 +1,87 @@
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { readFile } from 'node:fs/promises';
import vm from 'node:vm';
import packageSha256, {
sha224 as packageSha224,
sha256 as namedPackageSha256
} from 'js-sha256';
import browserSha256, {
sha224 as browserSha224
} from '../src/index.mjs';
const require = createRequire(import.meta.url);
const commonJs = require('../build/sha256.cjs');
const nodeCommonJs = require('js-sha256');
const SHA256_ABC = 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad';
const SHA224_ABC = '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7';
const HMAC_ABC = '9c196e32dc0175f86f4b1cb89289d6619de6bee699e4c378e68309ed97a1a6ab';
function testContract(name, sha256, sha224) {
assert.equal(sha256('abc'), SHA256_ABC, `${name}: SHA-256`);
assert.equal(sha224('abc'), SHA224_ABC, `${name}: SHA-224`);
assert.equal(sha256.hmac('key', 'abc'), HMAC_ABC, `${name}: HMAC`);
assert.equal(sha256.update('a').update('bc').hex(), SHA256_ABC, `${name}: streaming`);
assert.equal(sha256([97, 98, 99]), SHA256_ABC, `${name}: array`);
assert.equal(sha256(new Uint8Array([97, 98, 99])), SHA256_ABC, `${name}: typed array`);
assert.equal(sha256.sha256, sha256, `${name}: sha256 property`);
assert.equal(sha256.sha224, sha224, `${name}: sha224 property`);
}
function testStreamingOutputs(name, algorithm, expected) {
const hasher = algorithm.create().update('a').update('bc');
assert.equal(hasher.hex(), expected, `${name}: hex`);
assert.equal(hasher.toString(), expected, `${name}: toString`);
assert.deepEqual(hasher.array(), Array.from(Buffer.from(expected, 'hex')), `${name}: array`);
assert.deepEqual(hasher.digest(), hasher.array(), `${name}: digest`);
assert.equal(
Buffer.from(hasher.arrayBuffer()).toString('hex'),
expected,
`${name}: arrayBuffer`
);
assert.equal(hasher.hex(), expected, `${name}: repeated output`);
}
function testHmacStreamingOutputs(name, hmac) {
const hasher = hmac.create('key').update('a').update('bc');
assert.equal(hasher.hex(), HMAC_ABC, `${name}: hex`);
assert.equal(hasher.toString(), HMAC_ABC, `${name}: toString`);
assert.deepEqual(hasher.array(), Array.from(Buffer.from(HMAC_ABC, 'hex')), `${name}: array`);
assert.deepEqual(hasher.digest(), hasher.array(), `${name}: digest`);
assert.equal(
Buffer.from(hasher.arrayBuffer()).toString('hex'),
HMAC_ABC,
`${name}: arrayBuffer`
);
assert.equal(hasher.hex(), HMAC_ABC, `${name}: repeated output`);
}
testContract('package ESM', packageSha256, packageSha224);
assert.equal(namedPackageSha256, packageSha256);
testStreamingOutputs('package ESM SHA-256 streaming', packageSha256, SHA256_ABC);
testStreamingOutputs('package ESM SHA-224 streaming', packageSha224, SHA224_ABC);
testHmacStreamingOutputs('package ESM HMAC streaming', packageSha256.hmac);
testContract('browser ESM', browserSha256, browserSha224);
testContract('generic CommonJS', commonJs, commonJs.sha224);
testContract('package CommonJS', nodeCommonJs, nodeCommonJs.sha224);
testStreamingOutputs('package CommonJS SHA-256 streaming', nodeCommonJs, SHA256_ABC);
testStreamingOutputs('package CommonJS SHA-224 streaming', nodeCommonJs.sha224, SHA224_ABC);
testHmacStreamingOutputs('package CommonJS HMAC streaming', nodeCommonJs.hmac);
const umdCode = await readFile(new URL('../build/sha256.min.js', import.meta.url), 'utf8');
const browserContext = vm.createContext({});
vm.runInContext(umdCode, browserContext);
testContract('browser UMD', browserContext.sha256, browserContext.sha224);
let amdSha256;
const amdContext = vm.createContext({
define(factory) {
amdSha256 = factory();
}
});
amdContext.define.amd = true;
vm.runInContext(umdCode, amdContext);
testContract('AMD', amdSha256, amdSha256.sha224);
console.log('Distribution contracts: PASS');