You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

loadScript.native.js 1.7KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. /**
  2. * Loads a script from a specific URL. React Native cannot load a JS
  3. * file/resource/URL via a <script> HTML element, so the implementation
  4. * fetches the specified {@code url} as plain text using {@link fetch()} and
  5. * then evaluates the fetched string as JavaScript code (using {@link eval()}).
  6. *
  7. * @param {string} url - The absolute URL from which the script is to be
  8. * (down)loaded.
  9. * @returns {void}
  10. */
  11. export function loadScript(url) {
  12. return new Promise((resolve, reject) => {
  13. // XXX The implementation of fetch on Android will throw an Exception on
  14. // the Java side which will break the app if the URL is invalid (which
  15. // the implementation of fetch on Android calls 'unexpected url'). In
  16. // order to try to prevent the breakage of the app, try to fail on an
  17. // invalid URL as soon as possible.
  18. const { hostname, pathname, protocol } = new URL(url);
  19. // XXX The standard URL implementation should throw an Error if the
  20. // specified URL is relative. Unfortunately, the polyfill used on
  21. // react-native does not.
  22. if (!hostname || !pathname || !protocol) {
  23. reject(`unexpected url: ${url}`);
  24. return;
  25. }
  26. fetch(url, { method: 'GET' })
  27. .then(response => {
  28. switch (response.status) {
  29. case 200:
  30. return response.responseText || response.text();
  31. default:
  32. throw response.statusText;
  33. }
  34. })
  35. .then(responseText => {
  36. eval.call(window, responseText); // eslint-disable-line no-eval
  37. })
  38. .then(resolve, reject);
  39. });
  40. }