UNPKG

pdq-wasm

Version:

WebAssembly bindings for Meta's PDQ perceptual image hashing algorithm

93 lines (83 loc) 2.51 kB
/** * Example Web Worker for PDQ hashing * * This worker demonstrates how to use pdq-wasm in a Web Worker environment. * It loads the WASM module and processes image files sent from the main thread. */ // Import PDQ in the worker // SECURITY NOTE: For production, self-host the files instead of using CDN // This example uses a pinned version for reproducibility // Version is auto-updated by `npm version` command via scripts/update-version-in-examples.js importScripts('https://unpkg.com/pdq-wasm@0.3.9/dist/browser.js'); // Initialize PDQ in the worker async function init() { try { await PDQ.initWorker({ // Pin to specific version to ensure reproducibility and security wasmUrl: 'https://unpkg.com/pdq-wasm@0.3.9/wasm/pdq.wasm' }); console.log('PDQ initialized in worker'); self.postMessage({ type: 'ready' }); } catch (error) { console.error('Failed to initialize PDQ:', error); self.postMessage({ type: 'error', error: error.message }); } } // Handle messages from main thread self.onmessage = async (event) => { const { type, data } = event.data; // Validate message structure if (typeof type !== 'string') { self.postMessage({ type: 'error', error: 'Invalid message format' }); return; } switch (type) { case 'init': await init(); break; case 'hash': // Validate input if (!data || !(data.file instanceof Blob)) { self.postMessage({ type: 'error', error: 'Invalid file object', filename: data?.filename }); return; } // Add size limit to prevent DOS attacks const MAX_SIZE = 50 * 1024 * 1024; // 50MB if (data.file.size > MAX_SIZE) { self.postMessage({ type: 'error', error: `File too large: ${(data.file.size / 1024 / 1024).toFixed(1)}MB (max: 50MB)`, filename: data.filename }); return; } try { // Use generateHashFromBlob which works in workers const hash = await generateHashFromBlob(data.file); self.postMessage({ type: 'hash-result', hash, filename: data.filename }); } catch (error) { self.postMessage({ type: 'error', error: error.message, filename: data.filename }); } break; default: self.postMessage({ type: 'error', error: `Unknown message type: ${type}` }); } };