timepiece/node_modules/dynamic-import-polyfill/initialize.mjs

74 lines
2.6 KiB
JavaScript

/*
Copyright (c) 2018 uupaa and 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Creates a global function (defaulting to `self.__import__()`) that can
* dynamically import modules. In browsers that support native dynamic
* `import()`, the function defers to using that, otherwise a small polyfill
* is used that creates a new module script and resolves once the module
* is loaded.
*
* @param {Object} [options]
* @param {string} [options.modulePath='.'] A path that relative import URLs
* are resolved from. This is needed since this polyfill creates script
* elements, and relative imports inside script elements will resolve
* relative to the page URL. Set this option to have URLs resolve relative
* to a different path (typically the location of your deployed modules
* directory).
* @param {string} [importFunctionName='__import__'] The name to use for the
* global import function this polyfill will create. Since `import` is
* a keyword in JavaScript, it's not possible to polyfill dynamic import
* by creating a global function named `import()`. Thus, a different
* name must be used.
*/
export function initialize({
modulePath = '.',
importFunctionName = '__import__',
} = {}) {
try {
self[importFunctionName] = new Function('u', `return import(u)`);
} catch (error) {
const baseURL = new URL(modulePath, location);
const cleanup = (script) => {
URL.revokeObjectURL(script.src);
script.remove();
};
self[importFunctionName] = (url) => new Promise((resolve, reject) => {
const absURL = new URL(url, baseURL);
// If the module has already been imported, resolve immediately.
if (self[importFunctionName].moduleMap[absURL]) {
return resolve(self[importFunctionName].moduleMap[absURL]);
}
const moduleBlob = new Blob([
`import * as m from '${absURL}';`,
`${importFunctionName}.moduleMap['${absURL}']=m;`,
], {type: 'text/javascript'});
const script = Object.assign(document.createElement('script'), {
type: 'module',
src: URL.createObjectURL(moduleBlob),
onerror() {
reject(new Error(`Failed to import: ${url}`));
cleanup(script);
},
onload() {
resolve(self[importFunctionName].moduleMap[absURL]);
cleanup(script);
},
});
document.head.appendChild(script);
});
self[importFunctionName].moduleMap = {};
}
}