UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

201 lines (197 loc) 7.19 kB
'use strict'; var env = require('../env.js'); require('../error.js'); var path = require('../path.js'); var module_util = require('./util.js'); var path_util = require('../path/util.js'); var error_common = require('../error/common.js'); /** * The `module` module purified for the web. * @module */ function interop(module, strict = undefined) { if (typeof module === "function") { return module().then(mod => interop(mod, strict)); } else if (module instanceof Promise) { return module.then(mod => interop(mod, strict)); } let exports = module["module.exports"]; if (typeof exports !== "undefined") { return exports; } else if (isExportsObject(exports = module["default"])) { const hasEsModule = module["__esModule"] === true || exports["__esModule"] === true; if (hasEsModule) { return exports; } else if (strict) { return module; } const exportNames = (x) => x !== "default" && x !== "__esModule"; const moduleKeys = Object.getOwnPropertyNames(module) .filter(exportNames).sort(); const defaultKeys = Object.getOwnPropertyNames(exports) .filter(exportNames).sort(); if (String(moduleKeys) === String(defaultKeys) || (strict === false && !moduleKeys.length)) { return exports; } } return module; } function isExportsObject(module) { return typeof module === "object" && module !== null && !Array.isArray(module); } function isMain(importMeta) { var _a; if ("main" in importMeta && typeof importMeta["main"] === "boolean") { return importMeta["main"]; } if ("serviceWorker" in globalThis && "url" in importMeta) { // @ts-ignore return globalThis["serviceWorker"]["scriptURL"] === importMeta.url; } else if ((env.isDedicatedWorker || env.isSharedWorker) && "url" in importMeta && typeof location === "object" && location) { return importMeta.url === location.href; } if (typeof process === "object" && Array.isArray(process.argv) && process.argv.length) { if (!process.argv[1]) { // Node.js REPL or the program is executed by `node -e "code"`, // or the program is executed by itself. return ["<repl>", "[eval]"].includes(importMeta["id"]); } const filename = "url" in importMeta ? importMeta.url : ((_a = importMeta["filename"]) !== null && _a !== void 0 ? _a : process.argv[1]); const urlExt = path.extname(filename); let entry = process.argv[1]; if (!path.extname(entry) && urlExt) { // In Node.js, the extension name may be omitted when starting the script. entry += urlExt; } return path_util.equals(filename, entry, { ignoreFileProtocol: true }); } return false; } const importCache = new Map(); /** * Imports a script from the given URL to the current document, useful for * loading 3rd-party libraries dynamically in the browser. * * This function uses cache to avoid loading the same module multiple times. * * NOTE: This function is only available in the browser. * * @example * ```ts * import { importScript } from "@ayonli/jsext/module"; * * await importScript("https://code.jquery.com/jquery-3.7.1.min.js"); * * console.assert(typeof jQuery === "function"); * console.assert($ === jQuery); * ``` */ function importScript(url, options = {}) { if (!env.isBrowserWindow) { return Promise.reject(new error_common.NotSupportedError("This function is only available in the browser.")); } url = new URL(url, location.href).href; let cache = importCache.get(url); if (cache) { return cache; } cache = new Promise((resolve, reject) => { module_util.getObjectURL(url).then(_url => { const script = document.createElement("script"); script.src = _url; script.type = options.type === "module" ? "module" : "text/javascript"; script.setAttribute("data-src", url); script.onload = () => setTimeout(resolve, 0); script.onerror = () => reject(new error_common.NetworkError(`Failed to load script: ${url}`)); document.head.appendChild(script); }).catch(reject); }); importCache.set(url, cache); return cache; } /** * Imports a stylesheet from the given URL to the current document, useful for * loading 3rd-party libraries dynamically in the browser. * * This function uses cache to avoid loading the same module multiple times. * * NOTE: This function is only available in the browser. * * @example * ```ts * import { importStylesheet } from "@ayonli/jsext/module"; * * await importStylesheet("https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css"); * ``` */ function importStylesheet(url) { if (!env.isBrowserWindow) { return Promise.reject(new error_common.NotSupportedError("This function is only available in the browser.")); } url = new URL(url, location.href).href; let cache = importCache.get(url); if (cache) { return cache; } cache = new Promise((resolve, reject) => { module_util.getObjectURL(url, "text/css").then(_url => { const link = document.createElement("link"); link.href = _url; link.rel = "stylesheet"; link.setAttribute("data-src", url); link.onload = () => setTimeout(resolve, 0); link.onerror = () => reject(new error_common.NetworkError(`Failed to load stylesheet: ${url}`)); document.head.appendChild(link); }).catch(reject); }); importCache.set(url, cache); return cache; } const wasmCache = new Map(); async function importWasm(module, imports = undefined) { if (module instanceof WebAssembly.Module) { let cache = wasmCache.get(module); if (!cache) { cache = WebAssembly.instantiate(module, imports).then(ins => ins.exports); wasmCache.set(module, cache); } return await cache; } const url = typeof module === "string" ? module : module.href; if (typeof WebAssembly.instantiateStreaming === "function") { let cache = wasmCache.get(url); if (!cache) { cache = fetch(url) .then(res => WebAssembly.instantiateStreaming(res, imports)) .then(ins => ins.instance.exports); wasmCache.set(url, cache); } return await cache; } else { let cache = wasmCache.get(url); if (!cache) { cache = fetch(url) .then(res => res.arrayBuffer()) .then(buf => WebAssembly.instantiate(buf, imports)) .then(ins => ins.instance.exports); wasmCache.set(url, cache); } return await cache; } } exports.importScript = importScript; exports.importStylesheet = importStylesheet; exports.importWasm = importWasm; exports.interop = interop; exports.isMain = isMain; //# sourceMappingURL=web.js.map