UNPKG

ngx-extended-pdf-viewer

Version:

Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.

99 lines (89 loc) 3.93 kB
// #2687 #2536 Which pdf.js bundle can this browser run? // // Sets window.ngxExtendedPdfViewerCanRunModernJSCode; false routes the viewer to // the `*-es5.mjs` (legacy) bundle. The deciding check is Promise.withResolvers, // so the modern bundle starts at Chrome 119 / Edge 119 / Firefox 121 / Safari 17.4, // and everything below that must be covered by LEGACY_ENV_TARGETS in the fork's // gulpfile.mjs (currently Chrome/Edge 80, Firefox 78, Safari 13.1, iOS 13.4). // Change one side and you must change the other, or old browsers receive code // they cannot parse. // // THIS FILE EXISTS THREE TIMES and the copies must stay identical: // assets/op-chaining-support.js, bleeding-edge/op-chaining-support.js, and the // inline copy in lib/pdf-script-loader.service.ts (used when useInlineScripts). // pdf-script-loader.service.spec.ts fails if they drift. new (function () { class BrowserCompatibilityTester { // Does your browser doesn't support private fields? #privateField; constructor() { // Does your browser support the logical assignment operators? let x = false; x ||= true; this.#privateMethod(); } // Does your browser doesn't support private methods? #privateMethod() { // check the the browser supports string.at() return 'hello'.at(4); } supportsOptionalChaining() { const optionalChaining = { support: true, }; return optionalChaining?.support; } } function supportsPromiseWithResolvers() { const iframe = document.createElement('iframe'); document.firstElementChild.append(iframe); const useLegacyPdfViewer = 'withResolvers' in iframe.contentWindow['Promise']; iframe.parentElement.removeChild(iframe); return useLegacyPdfViewer; } // #2687 The discriminator: the newest thing the modern bundle needs. // // pdf.js 6.x calls iterator helpers on Map/Set (`.values().some()`, // `.keys().filter().toArray()`, ...) and the modern bundle ships NO core-js // polyfills (SKIP_BABEL, and Babel transpiles syntax but never APIs). Iterator // helpers arrived later than Promise.withResolvers in every engine // (Chrome/Edge 122+, Firefox 131+, Safari/iOS 18.4+ versus 119/121/17.4), so // this single check subsumes the Promise one and is what actually decides // whether the modern bundle will run. Without it, e.g. Safari 17.4-18.3 loads // the modern viewer and dies on the first Map iterator. function supportsIteratorHelpers() { try { const iterator = [].values(); return typeof iterator.map === 'function' && typeof iterator.toArray === 'function'; } catch (e) { return false; } } const supportsOptionalChaining = new BrowserCompatibilityTester().supportsOptionalChaining(); const supportModernPromises = supportsPromiseWithResolvers(); window.ngxExtendedPdfViewerCanRunModernJSCode = supportsOptionalChaining && supportModernPromises && supportsIteratorHelpers(); // #1321 AbortSignal.any() polyfill for the modern build's main thread. // pdf.js v6 calls AbortSignal.any() directly; Safari 17.4 shipped // Promise.withResolvers (our "modern" gate) before AbortSignal.any was // added in 17.5. Shimming it here keeps that thin window on the modern // build instead of forcing a fallback to viewer-es5.mjs. The legacy // build gets the same polyfill via core-js + Babel. if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.any !== 'function') { AbortSignal.any = function (signals) { const controller = new AbortController(); for (const signal of signals) { if (signal.aborted) { controller.abort(signal.reason); return controller.signal; } signal.addEventListener( 'abort', () => controller.abort(signal.reason), { once: true } ); } return controller.signal; }; } })();