{
  "version": 3,
  "sources": ["../src/feature-detection.ts"],
  "sourcesContent": ["/**\n * Internal dependencies\n */\nimport type { ImageDimensions } from './get-image-dimensions';\n\ninterface NavigatorNetworkInformation {\n\tsaveData: boolean;\n\teffectiveType: 'slow-2g' | '2g' | '3g' | '4g';\n}\n\ninterface NavigatorExtended extends Navigator {\n\tdeviceMemory?: number;\n\tconnection?: NavigatorNetworkInformation;\n}\n\n/**\n * Result of client-side media processing support detection.\n */\nexport interface FeatureDetectionResult {\n\t/**\n\t * Whether client-side media processing is supported.\n\t */\n\tsupported: boolean;\n\t/**\n\t * Reason why client-side media processing is not supported (if applicable).\n\t */\n\treason?: string;\n}\n\n/**\n * Cached result of feature detection.\n */\nlet cachedResult: FeatureDetectionResult | null = null;\n\n/**\n * Detects whether the browser supports client-side media processing.\n *\n * Checks (in order of evaluation):\n * 1. WebAssembly support (required for wasm-vips).\n * 2. SharedArrayBuffer support (required for WASM threading; relies on\n *    cross-origin isolation headers being set).\n * 3. Web Worker support (baseline requirement for the processing worker).\n * 4. Device memory: disables on devices reporting ≤ 2 GB of RAM.\n * 5. Hardware concurrency: disables on devices reporting fewer than 2 CPU cores.\n * 6. Network conditions: disables when the data saver flag is on, or when the\n *    connection's effective type is `slow-2g` or `2g`.\n * 7. CSP compatibility for blob URL workers: a probe Worker is created from a\n *    blob: URL to confirm the site's Content Security Policy permits inline\n *    worker creation (`worker-src` must allow `blob:`).\n *\n * Results are cached after the first call. Use `clearFeatureDetectionCache()` to reset.\n *\n * @return Feature detection result with supported status and reason if not supported.\n */\nexport function detectClientSideMediaSupport(): FeatureDetectionResult {\n\t// Return cached result if available.\n\tif ( cachedResult !== null ) {\n\t\treturn cachedResult;\n\t}\n\n\t// Check WebAssembly support.\n\tif ( typeof WebAssembly === 'undefined' ) {\n\t\tcachedResult = {\n\t\t\tsupported: false,\n\t\t\treason: 'WebAssembly is not supported in this browser.',\n\t\t};\n\t\treturn cachedResult;\n\t}\n\n\t// Check SharedArrayBuffer support (required for WASM threading).\n\tif ( typeof SharedArrayBuffer === 'undefined' ) {\n\t\tcachedResult = {\n\t\t\tsupported: false,\n\t\t\treason: 'SharedArrayBuffer is not available. This may be due to missing cross-origin isolation headers.',\n\t\t};\n\t\treturn cachedResult;\n\t}\n\n\t// Check Web Worker support.\n\tif ( typeof Worker === 'undefined' ) {\n\t\tcachedResult = {\n\t\t\tsupported: false,\n\t\t\treason: 'Web Workers are not supported in this browser.',\n\t\t};\n\t\treturn cachedResult;\n\t}\n\n\t// Check device memory.\n\tif (\n\t\ttypeof navigator !== 'undefined' &&\n\t\t'deviceMemory' in navigator &&\n\t\t( navigator as NavigatorExtended ).deviceMemory! <= 2\n\t) {\n\t\tcachedResult = {\n\t\t\tsupported: false,\n\t\t\treason: 'Device has insufficient memory for client-side media processing.',\n\t\t};\n\t\treturn cachedResult;\n\t}\n\n\t// Check hardware concurrency (number of CPU cores).\n\tif (\n\t\ttypeof navigator !== 'undefined' &&\n\t\t'hardwareConcurrency' in navigator &&\n\t\tnavigator.hardwareConcurrency < 2\n\t) {\n\t\tcachedResult = {\n\t\t\tsupported: false,\n\t\t\treason: 'Device has insufficient CPU cores for client-side media processing.',\n\t\t};\n\t\treturn cachedResult;\n\t}\n\n\t// Check network conditions.\n\tif ( typeof navigator !== 'undefined' ) {\n\t\tconst connection = ( navigator as NavigatorExtended ).connection;\n\t\tif ( connection ) {\n\t\t\tif ( connection.saveData ) {\n\t\t\t\tcachedResult = {\n\t\t\t\t\tsupported: false,\n\t\t\t\t\treason: 'Data saver mode is enabled.',\n\t\t\t\t};\n\t\t\t\treturn cachedResult;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tconnection.effectiveType === 'slow-2g' ||\n\t\t\t\tconnection.effectiveType === '2g'\n\t\t\t) {\n\t\t\t\tcachedResult = {\n\t\t\t\t\tsupported: false,\n\t\t\t\t\treason: 'Network connection is too slow for client-side media processing.',\n\t\t\t\t};\n\t\t\t\treturn cachedResult;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check that blob URL workers are allowed by CSP.\n\t// Security plugins often set a strict worker-src directive that blocks blob: URLs,\n\t// which would prevent creating the WASM processing worker at runtime.\n\tif ( typeof window !== 'undefined' ) {\n\t\ttry {\n\t\t\tconst testBlob = new Blob( [ '' ], {\n\t\t\t\ttype: 'application/javascript',\n\t\t\t} );\n\t\t\tconst testUrl = URL.createObjectURL( testBlob );\n\t\t\ttry {\n\t\t\t\tconst testWorker = new Worker( testUrl );\n\t\t\t\ttestWorker.terminate();\n\t\t\t} finally {\n\t\t\t\tURL.revokeObjectURL( testUrl );\n\t\t\t}\n\t\t} catch {\n\t\t\tcachedResult = {\n\t\t\t\tsupported: false,\n\t\t\t\treason: \"The site's Content Security Policy (CSP) does not allow blob: workers. The worker-src directive must include blob: to enable client-side media processing.\",\n\t\t\t};\n\t\t\treturn cachedResult;\n\t\t}\n\t}\n\n\tcachedResult = { supported: true };\n\treturn cachedResult;\n}\n\n/**\n * Returns whether client-side media processing is supported.\n *\n * This is a convenience function that returns just the boolean result.\n *\n * @return Whether client-side media processing is supported.\n */\nexport function isClientSideMediaSupported(): boolean {\n\treturn detectClientSideMediaSupport().supported;\n}\n\n/**\n * Detects whether the browser can decode HEIC images via canvas APIs.\n *\n * This checks for createImageBitmap and OffscreenCanvas support,\n * which are sufficient to convert HEIC to JPEG without VIPS/WASM.\n * Safari supports both APIs and can natively decode HEIC via\n * createImageBitmap(), leveraging macOS platform codecs.\n *\n * @return Whether HEIC canvas-based processing is supported.\n */\nexport function isHeicCanvasSupported(): boolean {\n\treturn (\n\t\ttypeof createImageBitmap !== 'undefined' &&\n\t\ttypeof OffscreenCanvas !== 'undefined'\n\t);\n}\n\n/**\n * Clears the cached feature detection result.\n *\n * This is primarily useful for testing purposes.\n */\nexport function clearFeatureDetectionCache(): void {\n\tcachedResult = null;\n}\n\n/**\n * Estimated bytes of WASM memory required per decoded pixel.\n *\n * A decoded image needs roughly width * height * 4 bytes (RGBA) in memory,\n * plus additional working buffers while vips processes and re-encodes it.\n * Four bytes per pixel is a deliberately conservative lower bound.\n */\nconst BYTES_PER_PIXEL = 4;\n\n/**\n * Memory budget (in bytes) for processing interlaced images client-side.\n *\n * wasm-vips is hard-capped at 1 GiB of WASM memory. Progressive JPEGs and\n * Adam7-interlaced PNGs cannot be decoded with shrink-on-load, so the entire\n * image must be buffered at once. A tighter ~0.5 GiB budget leaves headroom\n * for the encode step and avoids the out-of-memory failures these images hit.\n */\nconst INTERLACED_MEMORY_BUDGET = 0.5 * 1024 * 1024 * 1024;\n\n/**\n * Memory budget (in bytes) for processing non-interlaced images client-side.\n *\n * Baseline images can be shrunk during decode, so vips needs far less peak\n * memory. A generous ~0.9 GiB budget acts as a backstop against extreme sizes\n * while leaving the vast majority of real-world uploads on the client.\n */\nconst BASELINE_MEMORY_BUDGET = 0.9 * 1024 * 1024 * 1024;\n\n/**\n * Determines whether an image is too large to process client-side.\n *\n * Very large images, especially interlaced/progressive ones, can exceed the\n * 1 GiB wasm-vips memory cap and fail to process. Such images are better\n * handled by the server, which has no comparable per-image memory ceiling.\n *\n * @param dimensions The image's parsed dimensions and interlacing.\n * @return Whether the image's estimated memory use exceeds the client budget.\n */\nexport function exceedsClientProcessingMemory(\n\tdimensions: ImageDimensions\n): boolean {\n\tconst { width, height, interlaced } = dimensions;\n\tconst estimatedBytes = width * height * BYTES_PER_PIXEL;\n\tconst budget = interlaced\n\t\t? INTERLACED_MEMORY_BUDGET\n\t\t: BASELINE_MEMORY_BUDGET;\n\treturn estimatedBytes > budget;\n}\n"],
  "mappings": ";AAgCA,IAAI,eAA8C;AAsB3C,SAAS,+BAAuD;AAEtE,MAAK,iBAAiB,MAAO;AAC5B,WAAO;AAAA,EACR;AAGA,MAAK,OAAO,gBAAgB,aAAc;AACzC,mBAAe;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAGA,MAAK,OAAO,sBAAsB,aAAc;AAC/C,mBAAe;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAGA,MAAK,OAAO,WAAW,aAAc;AACpC,mBAAe;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAGA,MACC,OAAO,cAAc,eACrB,kBAAkB,aAChB,UAAiC,gBAAiB,GACnD;AACD,mBAAe;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAGA,MACC,OAAO,cAAc,eACrB,yBAAyB,aACzB,UAAU,sBAAsB,GAC/B;AACD,mBAAe;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAGA,MAAK,OAAO,cAAc,aAAc;AACvC,UAAM,aAAe,UAAiC;AACtD,QAAK,YAAa;AACjB,UAAK,WAAW,UAAW;AAC1B,uBAAe;AAAA,UACd,WAAW;AAAA,UACX,QAAQ;AAAA,QACT;AACA,eAAO;AAAA,MACR;AACA,UACC,WAAW,kBAAkB,aAC7B,WAAW,kBAAkB,MAC5B;AACD,uBAAe;AAAA,UACd,WAAW;AAAA,UACX,QAAQ;AAAA,QACT;AACA,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAKA,MAAK,OAAO,WAAW,aAAc;AACpC,QAAI;AACH,YAAM,WAAW,IAAI,KAAM,CAAE,EAAG,GAAG;AAAA,QAClC,MAAM;AAAA,MACP,CAAE;AACF,YAAM,UAAU,IAAI,gBAAiB,QAAS;AAC9C,UAAI;AACH,cAAM,aAAa,IAAI,OAAQ,OAAQ;AACvC,mBAAW,UAAU;AAAA,MACtB,UAAE;AACD,YAAI,gBAAiB,OAAQ;AAAA,MAC9B;AAAA,IACD,QAAQ;AACP,qBAAe;AAAA,QACd,WAAW;AAAA,QACX,QAAQ;AAAA,MACT;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAEA,iBAAe,EAAE,WAAW,KAAK;AACjC,SAAO;AACR;AASO,SAAS,6BAAsC;AACrD,SAAO,6BAA6B,EAAE;AACvC;AAYO,SAAS,wBAAiC;AAChD,SACC,OAAO,sBAAsB,eAC7B,OAAO,oBAAoB;AAE7B;AAOO,SAAS,6BAAmC;AAClD,iBAAe;AAChB;AASA,IAAM,kBAAkB;AAUxB,IAAM,2BAA2B,MAAM,OAAO,OAAO;AASrD,IAAM,yBAAyB,MAAM,OAAO,OAAO;AAY5C,SAAS,8BACf,YACU;AACV,QAAM,EAAE,OAAO,QAAQ,WAAW,IAAI;AACtC,QAAM,iBAAiB,QAAQ,SAAS;AACxC,QAAM,SAAS,aACZ,2BACA;AACH,SAAO,iBAAiB;AACzB;",
  "names": []
}
