Use bounded native SHA256 inside digest Workers

This commit is contained in:
2026-11-09 20:16:39 +08:00
parent fea813ac4f
commit 70bc134436
5 changed files with 52 additions and 2 deletions
@@ -0,0 +1,17 @@
import {fault} from '../canvas-core/values.ts';
import {importSourceDigest} from './import-integrity.ts';
// Each of the browser pool's two active Workers admits at most 64 MiB; larger inputs stream.
export const nativeDigestByteLimit=64*1024*1024;
/** Dedicated Worker only: whole-buffer native hashing never moves onto the UI thread.
* The host still owns cancellation by terminating the request's Worker. */
export async function digestWorkerSource(bytes:Blob,subtle:Pick<SubtleCrypto,'digest'>|null|undefined=globalThis.crypto?.subtle):Promise<string>{
if(!(bytes instanceof Blob))throw fault('invalid_digest_input');
if(subtle&&bytes.size<=nativeDigestByteLimit){
const input=await bytes.arrayBuffer(),digest=await subtle.digest('SHA-256',input);
if(digest.byteLength!==32)throw fault('invalid_digest_response');
return [...new Uint8Array(digest)].map(value=>value.toString(16).padStart(2,'0')).join('');
}
return importSourceDigest(bytes,undefined,{chunkBytes:1024*1024,yieldTask:()=>Promise.resolve()});
}
+2 -2
View File
@@ -1,8 +1,8 @@
import {importSourceDigest} from './import-integrity.ts';
import {digestWorkerSource} from './digest-worker-source.ts';
// Dedicated to one request. Host terminates on success/failure/abort; no storage, model or credentials here.
const scope=globalThis as unknown as {onmessage:((event:MessageEvent)=>void)|null;postMessage(value:unknown):void};
let accepted=false;
scope.onmessage=event=>{
const request=event.data;if(accepted||!request||request.version!==1||!Number.isSafeInteger(request.id)||request.id<1||!(request.bytes instanceof Blob))return;accepted=true;
void importSourceDigest(request.bytes,undefined,{chunkBytes:1024*1024,yieldTask:()=>Promise.resolve()}).then(sha256=>scope.postMessage({version:1,id:request.id,byteLength:request.bytes.size,sha256}),()=>scope.postMessage({version:1,id:request.id,byteLength:request.bytes.size,error:'digest_worker_failed'}));
void digestWorkerSource(request.bytes).then(sha256=>scope.postMessage({version:1,id:request.id,byteLength:request.bytes.size,sha256}),()=>scope.postMessage({version:1,id:request.id,byteLength:request.bytes.size,error:'digest_worker_failed'}));
};