/** * 专用 Worker 内的摘要算法选择:小于等于64MiB可用原生 SubtleCrypto,较大文件分块流式 SHA。 * 整缓冲读取只允许发生在 Worker,取消由宿主终止该请求的 Worker;本函数不访问存储或文档。 */ 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. /** 单任务 native 缓冲阈值,不是整个应用内存硬上限;总并发由外部 pool 决定。 */ 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. */ /** 验证 Blob,SubtleCrypto 存在且大小 ≤64MiB 时读取整个 ArrayBuffer 做 SHA-256,否则流式计算。 * 原生读/算失败直接传播,不自动切到流式重试;注入 subtle 应遵守原生 digest 的 ArrayBuffer 合同。 * 本函数无 signal,取消靠宿主终止 Worker;代码本身不检测当前线程,Worker 限制由装配调用方遵守。 * 阈值只限制此输入的整缓冲分配,未计 Blob/原生算法内部内存及其它并发 Worker。 */ export async function digestWorkerSource(bytes:Blob,subtle:Pick|null|undefined=globalThis.crypto?.subtle):Promise{ if(!(bytes instanceof Blob))throw fault('invalid_digest_input'); // native digest 必须返回32字节;输出固定64字符十六进制,不接受变长响应。 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(''); } // 每块 1MiB,块间 yieldTask 仅完成一个 Promise 微任务,不保证 Worker 消息队列获得宏任务机会。 // UI fallback 用 importSourceDigest 默认定时器让出;不要把这里的微任务策略移作 UI 响应性承诺。 return importSourceDigest(bytes,undefined,{chunkBytes:1024*1024,yieldTask:()=>Promise.resolve()}); }