import * as wasmWebp from './webp/decoder'; import * as browserWebp from './webp/decoder'; import { nativeDecode, sniffMimeType } from '../lib/util'; export interface Decoder { name: string; decode(blob: Blob): Promise; isSupported(): Promise; canHandleMimeType(mimeType: string): boolean; } // We load all decoders and filter out the unsupported ones. export const decodersPromise: Promise = Promise.all( [ browserWebp, wasmWebp, ] .map(async (decoder) => { if (await decoder.isSupported()) { return decoder; } return null; }), // TypeScript is not smart enough to realized that I’m filtering all the falsy // values here. ).then(list => list.filter(item => !!item)) as any as Promise; async function findDecodersByMimeType(mimeType: string): Promise { const decoders = await decodersPromise; return decoders.filter(decoder => decoder.canHandleMimeType(mimeType)); } export async function decodeImage(blob: Blob): Promise { const mimeType = await sniffMimeType(blob); const decoders = await findDecodersByMimeType(mimeType); if (decoders.length <= 0) { // If we can’t find a decoder, hailmary with the browser's decoders return nativeDecode(blob); } for (const decoder of decoders) { try { return await decoder.decode(blob); } catch { } } throw new Error('No decoder could decode image'); }