tc39 / proposal-dynamic-import

import() proposal for JavaScript
https://tc39.github.io/proposal-dynamic-import/
MIT License
1.86k stars 47 forks source link

importModule function in README does not work #61

Open hax opened 6 years ago

hax commented 6 years ago

https://github.com/tc39/proposal-dynamic-import#using-host-specific-mechanisms

function importModule(url) {
  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);
    script.type = "module";
    script.textContent = `import * as m from "${url}"; window.${tempGlobal} = m;`;

    script.onload = () => {
      resolve(window[tempGlobal]);
      delete window[tempGlobal];
      script.remove();
    };

    script.onerror = () => {
      reject(new Error("Failed to load module script with URL " + url));
      delete window[tempGlobal];
      script.remove();
    };

    document.documentElement.appendChild(script);
  });
}

This importModule function does not work, because a inline script without src attribute will never trigger load event.

ephys commented 6 years ago

Version that does not use onload:

function importModule(url) {
  // escape characters that are used to delimit the module URL.
  // this way the following module works: 'data:text/javascript,console.log("hello")'
  url = url.replace(/\\/g, '\\\\').replace(/"/g, '\\"');

  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);

    function cleanup() {
      delete window[tempGlobal]; 
      script.remove();
    }

    window[tempGlobal] = function (module) {
      cleanup();
      resolve(module);
    };

    script.type = "module";
    script.textContent = `import * as m from "${url}"; window.${tempGlobal}(m);`;

    script.onerror = () => {
      reject(new Error("Failed to load module script with URL " + url));
      cleanup();
    };

    document.documentElement.appendChild(script);
  });
}

Note that the returned promise does not reject when the module identifier is not valid (eg importModule('')), couldn't get that to work (it stays stuck in a pending state)