{"version":3,"file":"dom.cjs","names":["warn"],"sources":["../src/dom.ts"],"sourcesContent":["import type { CreateScriptHookDom, CreateScriptHookReturnDom } from './types';\nimport { warn } from './utils';\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function safeWrapper<T extends (...args: Array<any>) => any>(\n  callback: T,\n  disableWarn?: boolean,\n): Promise<ReturnType<T> | undefined> {\n  try {\n    const res = await callback();\n    return res;\n  } catch (e) {\n    !disableWarn && warn(e);\n    return;\n  }\n}\n\nexport function isStaticResourcesEqual(url1: string, url2: string): boolean {\n  const REG_EXP = /^(https?:)?\\/\\//i;\n  // Transform url1 and url2 into relative paths\n  const relativeUrl1 = url1.replace(REG_EXP, '').replace(/\\/$/, '');\n  const relativeUrl2 = url2.replace(REG_EXP, '').replace(/\\/$/, '');\n  // Check if the relative paths are identical\n  return relativeUrl1 === relativeUrl2;\n}\n\nexport function createScript(info: {\n  url: string;\n  cb?: (value: void | PromiseLike<void>) => void;\n  onErrorCallback?: (error: Error) => void;\n  attrs?: Record<string, any>;\n  needDeleteScript?: boolean;\n  createScriptHook?: CreateScriptHookDom;\n}): { script: HTMLScriptElement; needAttach: boolean } {\n  // Retrieve the existing script element by its src attribute\n  let script: HTMLScriptElement | null = null;\n  let needAttach = true;\n  let timeout = 20000;\n  let timeoutId: NodeJS.Timeout;\n  const scripts = document.getElementsByTagName('script');\n\n  for (let i = 0; i < scripts.length; i++) {\n    const s = scripts[i];\n    const scriptSrc = s.getAttribute('src');\n    if (scriptSrc && isStaticResourcesEqual(scriptSrc, info.url)) {\n      script = s;\n      needAttach = false;\n      break;\n    }\n  }\n\n  if (!script) {\n    const attrs = info.attrs;\n    script = document.createElement('script');\n    script.type = attrs?.['type'] === 'module' ? 'module' : 'text/javascript';\n    let createScriptRes: CreateScriptHookReturnDom = undefined;\n    if (info.createScriptHook) {\n      createScriptRes = info.createScriptHook(info.url, info.attrs);\n\n      if (createScriptRes instanceof HTMLScriptElement) {\n        script = createScriptRes;\n      } else if (typeof createScriptRes === 'object') {\n        if ('script' in createScriptRes && createScriptRes.script) {\n          script = createScriptRes.script;\n        }\n        if ('timeout' in createScriptRes && createScriptRes.timeout) {\n          timeout = createScriptRes.timeout;\n        }\n      }\n    }\n    if (!script.src) {\n      script.src = info.url;\n    }\n    if (attrs && !createScriptRes) {\n      Object.keys(attrs).forEach((name) => {\n        if (script) {\n          if (name === 'async' || name === 'defer') {\n            script[name] = attrs[name];\n            // Attributes that do not exist are considered overridden\n          } else if (!script.getAttribute(name)) {\n            script.setAttribute(name, attrs[name]);\n          }\n        }\n      });\n    }\n  }\n\n  // Capture JS runtime errors thrown by this script's IIFE during execution.\n  // The browser still fires onload even when the script throws, so without this\n  // listener the execution error would silently become an uncaught global exception.\n  let executionError: Error | null = null;\n  const executionErrorHandler =\n    typeof window !== 'undefined'\n      ? (evt: ErrorEvent) => {\n          if (evt.filename && isStaticResourcesEqual(evt.filename, info.url)) {\n            const err = new Error(\n              `ScriptExecutionError: Script \"${info.url}\" loaded but threw a runtime error during execution: ${evt.message} (${evt.filename}:${evt.lineno}:${evt.colno})`,\n            );\n            err.name = 'ScriptExecutionError';\n            executionError = err;\n          }\n        }\n      : null;\n  if (executionErrorHandler) {\n    window.addEventListener('error', executionErrorHandler);\n  }\n\n  const onScriptComplete = async (\n    prev: OnErrorEventHandler | GlobalEventHandlers['onload'] | null,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    event: any,\n  ): Promise<void> => {\n    clearTimeout(timeoutId);\n    if (executionErrorHandler) {\n      window.removeEventListener('error', executionErrorHandler);\n    }\n    const onScriptCompleteCallback = () => {\n      if (event?.type === 'error') {\n        const networkError = new Error(\n          event?.isTimeout\n            ? `ScriptNetworkError: Script \"${info.url}\" timed out.`\n            : `ScriptNetworkError: Failed to load script \"${info.url}\" - the script URL is unreachable or the server returned an error (network failure, 404, CORS, etc.)`,\n        );\n        networkError.name = 'ScriptNetworkError';\n        info?.onErrorCallback && info?.onErrorCallback(networkError);\n      } else if (executionError) {\n        // Script fetched OK (onload fired) but IIFE threw during execution.\n        info?.onErrorCallback && info?.onErrorCallback(executionError);\n      } else {\n        info?.cb && info?.cb();\n      }\n    };\n\n    // Prevent memory leaks in IE.\n    if (script) {\n      script.onerror = null;\n      script.onload = null;\n      safeWrapper(() => {\n        const { needDeleteScript = true } = info;\n        if (needDeleteScript) {\n          script?.parentNode && script.parentNode.removeChild(script);\n        }\n      });\n      if (prev && typeof prev === 'function') {\n        const result = (prev as any)(event);\n        if (result instanceof Promise) {\n          const res = await result;\n          onScriptCompleteCallback();\n          return res;\n        }\n        onScriptCompleteCallback();\n        return result;\n      }\n    }\n    onScriptCompleteCallback();\n  };\n\n  script.onerror = onScriptComplete.bind(null, script.onerror);\n  script.onload = onScriptComplete.bind(null, script.onload);\n\n  timeoutId = setTimeout(() => {\n    onScriptComplete(null, { type: 'error', isTimeout: true });\n  }, timeout);\n\n  return { script, needAttach };\n}\n\nexport function createLink(info: {\n  url: string;\n  cb?: (value: void | PromiseLike<void>) => void;\n  onErrorCallback?: (error: Error) => void;\n  attrs: Record<string, string>;\n  needDeleteLink?: boolean;\n  createLinkHook?: (\n    url: string,\n    attrs?: Record<string, any>,\n  ) => HTMLLinkElement | void;\n}) {\n  // <link rel=\"preload\" href=\"script.js\" as=\"script\">\n\n  // Retrieve the existing script element by its src attribute\n  let link: HTMLLinkElement | null = null;\n  let needAttach = true;\n  const links = document.getElementsByTagName('link');\n  for (let i = 0; i < links.length; i++) {\n    const l = links[i];\n    const linkHref = l.getAttribute('href');\n    const linkRel = l.getAttribute('rel');\n    if (\n      linkHref &&\n      isStaticResourcesEqual(linkHref, info.url) &&\n      linkRel === info.attrs['rel']\n    ) {\n      link = l;\n      needAttach = false;\n      break;\n    }\n  }\n\n  if (!link) {\n    link = document.createElement('link');\n    link.setAttribute('href', info.url);\n\n    let createLinkRes: void | HTMLLinkElement = undefined;\n    const attrs = info.attrs;\n\n    if (info.createLinkHook) {\n      createLinkRes = info.createLinkHook(info.url, attrs);\n      if (createLinkRes instanceof HTMLLinkElement) {\n        link = createLinkRes;\n      }\n    }\n\n    if (attrs && !createLinkRes) {\n      Object.keys(attrs).forEach((name) => {\n        if (link && !link.getAttribute(name)) {\n          link.setAttribute(name, attrs[name]);\n        }\n      });\n    }\n  }\n\n  const onLinkComplete = (\n    prev: OnErrorEventHandler | GlobalEventHandlers['onload'] | null,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    event: any,\n  ): void => {\n    const onLinkCompleteCallback = () => {\n      if (event?.type === 'error') {\n        info?.onErrorCallback && info?.onErrorCallback(event);\n      } else {\n        info?.cb && info?.cb();\n      }\n    };\n    // Prevent memory leaks in IE.\n    if (link) {\n      link.onerror = null;\n      link.onload = null;\n      safeWrapper(() => {\n        const { needDeleteLink = true } = info;\n        if (needDeleteLink) {\n          link?.parentNode && link.parentNode.removeChild(link);\n        }\n      });\n      if (prev) {\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        const res = (prev as any)(event);\n        onLinkCompleteCallback();\n        return res;\n      }\n    }\n    onLinkCompleteCallback();\n  };\n\n  link.onerror = onLinkComplete.bind(null, link.onerror);\n  link.onload = onLinkComplete.bind(null, link.onload);\n\n  return { link, needAttach };\n}\n\nexport function loadScript(\n  url: string,\n  info: {\n    attrs?: Record<string, any>;\n    createScriptHook?: CreateScriptHookDom;\n  },\n) {\n  const { attrs = {}, createScriptHook } = info;\n  return new Promise<void>((resolve, reject) => {\n    const { script, needAttach } = createScript({\n      url,\n      cb: resolve,\n      onErrorCallback: reject,\n      attrs: {\n        fetchpriority: 'high',\n        ...attrs,\n      },\n      createScriptHook,\n      needDeleteScript: true,\n    });\n    needAttach && document.head.appendChild(script);\n  });\n}\n"],"mappings":"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"}