UNPKG

@expo/metro-runtime

Version:

Tools for making advanced Metro bundler features work

91 lines (79 loc) 2.65 kB
/** * Copyright © 2022 650 Industries. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const currentSrc = typeof document !== 'undefined' && document.currentScript ? ('src' in document.currentScript && document.currentScript.src) || null : null; // Basically `__webpack_require__.l`. export function fetchThenEvalAsync( url: string, { scriptType, nonce, crossOrigin, }: { scriptType?: string; nonce?: string; crossOrigin?: string } = {} ): Promise<void> { if ( typeof window === 'undefined' || // In development, use the fetch/eval method to detect the server error codes and parse bundler errors for the error overlay. __DEV__ ) { return require('./fetchThenEvalJs').fetchThenEvalAsync(url); } return new Promise<void>((resolve, reject) => { const script = document.createElement('script'); if (scriptType) script.type = scriptType; if (nonce) script.setAttribute('nonce', nonce); // script.setAttribute('data-expo-metro', ...); script.src = url; if (crossOrigin && script.src.indexOf(window.location.origin + '/') !== 0) { script.crossOrigin = crossOrigin; } script.onload = () => { script.parentNode && script.parentNode.removeChild(script); resolve(); }; // Create a new error object to preserve the original stack trace. const error = new AsyncRequireError(); // Server error or network error. script.onerror = (ev) => { let event: Event; if (typeof ev === 'string') { event = { type: 'error', target: { // @ts-expect-error src: event, }, }; } else { event = ev; } const errorType = event && (event.type === 'load' ? 'missing' : event.type); // @ts-expect-error const realSrc = event?.target?.src; error.message = 'Loading module ' + url + ' failed.\n(' + errorType + ': ' + realSrc + ')'; error.type = errorType; error.request = realSrc; script.parentNode && script.parentNode.removeChild(script); reject(error); }; if (script.src === currentSrc) { // NOTE(kitten): We always prevent `fetchThenEval` from loading the "current script". // This points at our entrypoint bundle, and we should never reload and reevaluate the // entrypoint bundle resolve(); } else { document.head.appendChild(script); } }); } class AsyncRequireError extends Error { readonly name = 'AsyncRequireError'; type?: string; request?: string; }