Skip to content

Commit 016be86

Browse files
committed
v2.4.0 follow-up: drop ReadableStream global polyfill, scope it to the spec
The original v2.4.0 spec drove sha256Stream(blob) via a fake-blob whose .stream() returned 'new ReadableStream(...)'. That required the test setup to polyfill ReadableStream/WritableStream/TransformStream onto the jsdom global object -- five new globals just for one new test file. Restructure: import { ReadableStream } from 'node:stream/web' directly inside the spec, scoped to the test file. The fake-blob still emits real WHATWG ReadableStream chunks, sha256Stream(blob) still drives the same .getReader() path production code uses in real browsers, and we do it in BOTH node and jsdom (55 tests, zero skips, zero global polyfills). The browser setup is back to its pre-v2.4.0 polyfill set.
1 parent 83172a8 commit 016be86

2 files changed

Lines changed: 12 additions & 14 deletions

File tree

jest.config.browser.setup.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,8 @@ global.TextDecoder = util.TextDecoder;
1414
// add this too
1515
global.Uint8Array = Uint8Array;
1616

17-
const { DecompressionStream, ReadableStream, WritableStream, TransformStream } = require('stream/web');
17+
const { DecompressionStream } = require('stream/web');
1818
global.DecompressionStream = DecompressionStream;
19-
// jsdom doesn't expose the WHATWG Streams API; sha256Stream() reads
20-
// `Blob.prototype.stream()` which returns a ReadableStream<Uint8Array>.
21-
global.ReadableStream = ReadableStream;
22-
global.WritableStream = WritableStream;
23-
global.TransformStream = TransformStream;
2419

2520
// WebCrypto polyfill for jsdom -- the OTS verifier uses crypto.subtle.digest
2621
// for SHA-1 / SHA-256. Real browsers expose this; jsdom doesn't, so we

src/lib/sha256-stream.spec.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ReadableStream } from 'stream/web';
12
import { sha256Stream, sha256StreamFromIterable } from './sha256-stream';
23
import { createHash } from './sha256-uint8array';
34

@@ -37,10 +38,13 @@ function fillRandom(bytes: Uint8Array, seed: number): Uint8Array {
3738
return bytes;
3839
}
3940

40-
/** Polyfill a Blob-like object whose `stream()` method emits the given
41-
* bytes in chunks of `chunkSize`. Lets us drive sha256Stream() from
42-
* test code without depending on the `Blob` constructor's stream
43-
* semantics across environments. */
41+
/** Build a Blob-shaped object whose `.stream()` emits the given bytes in
42+
* `chunkSize`-sized chunks. We construct the ReadableStream from
43+
* `node:stream/web` ourselves rather than relying on `Blob.prototype.stream()`
44+
* -- jsdom's Blob doesn't return a real WHATWG ReadableStream, and we
45+
* deliberately don't pollute the global namespace with a polyfill. By
46+
* importing locally, the spec drives sha256Stream(blob) through the same
47+
* reader/getReader path production code uses in real browsers. */
4448
function makeChunkedBlob(bytes: Uint8Array, chunkSize: number): Blob {
4549
return {
4650
size: bytes.length,
@@ -56,7 +60,9 @@ function makeChunkedBlob(bytes: Uint8Array, chunkSize: number): Blob {
5660
},
5761
});
5862
},
59-
// Required Blob methods we don't use; satisfy the type at runtime via casts.
63+
// We never call these in production through sha256Stream, but the type
64+
// demands them. Stub them out -- a runtime call would surface the
65+
// mistake immediately.
6066
arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength),
6167
text: async () => '',
6268
slice: () => new Blob([]),
@@ -156,9 +162,6 @@ describe('sha256Stream — cross-validation vs one-shot hash', () => {
156162
// junk, so we re-verify on every test run.
157163

158164
describe('sha256Stream — agrees with crypto.subtle.digest (WebCrypto)', () => {
159-
// Skip cleanly if WebCrypto isn't present (e.g. very old Node without
160-
// the polyfill) -- our jest setup polyfills it, so this should never
161-
// skip in practice.
162165
const cryptoOk = typeof crypto !== 'undefined' && typeof crypto.subtle?.digest === 'function';
163166
const maybeIt = cryptoOk ? it : it.skip;
164167

0 commit comments

Comments
 (0)