diff --git a/components/apps/V86/useV86.ts b/components/apps/V86/useV86.ts index f73f6888..135a2d62 100644 --- a/components/apps/V86/useV86.ts +++ b/components/apps/V86/useV86.ts @@ -12,7 +12,7 @@ import type { import { useFileSystem } from 'contexts/fileSystem'; import { extname } from 'path'; import { useCallback, useEffect, useState } from 'react'; -import { bufferToUrl, loadScript } from 'utils/functions'; +import { bufferToUrl, loadFiles } from 'utils/functions'; const useV86 = ( url: string, @@ -25,7 +25,7 @@ const useV86 = ( useEffect(() => { if (!emulator) { fs?.readFile(url, (_error, contents = Buffer.from('')) => { - loadScript('/libs/v86/libv86.js', () => { + loadFiles(['/libs/v86/libv86.js']).then(() => { const isISO = extname(url).toLowerCase() === '.iso'; const { deviceMemory = 8 } = navigator as NavigatorWithMemory; const memoryRatio = deviceMemory / 8; diff --git a/utils/functions.ts b/utils/functions.ts index 92d76ef9..7c4c0fad 100644 --- a/utils/functions.ts +++ b/utils/functions.ts @@ -1,11 +1,52 @@ -export const loadScript = (src: string, callback: () => void): void => { - const script = document.createElement('script'); +import { extname } from 'path'; - script.src = src; - script.onload = () => callback?.(); +export const loadScript = (src: string): Promise => + new Promise((resolve, reject) => { + const loadedScripts = [...document.scripts]; - document.head.appendChild(script); -}; + if (loadedScripts.find((script) => script.src.endsWith(src))) { + resolve(new Event('Already loaded.')); + } else { + const script = document.createElement('script'); + + script.async = false; + script.src = src; + script.onerror = (event) => reject(event); + script.onload = (event) => resolve(event); + + document.head.appendChild(script); + } + }); + +export const loadStyle = (href: string): Promise => + new Promise((resolve, reject) => { + const loadedLinks = [...document.getElementsByTagName('link')]; + + if (loadedLinks.find((link) => link.href.endsWith(href))) { + resolve(new Event('Already loaded.')); + } else { + const link = document.createElement('link'); + + link.rel = 'stylesheet'; + link.href = href; + link.onerror = (event) => reject(event); + link.onload = (event) => resolve(event); + + document.head.appendChild(link); + } + }); + +export const loadFiles = async (files: string[]): Promise => + Promise.all( + files.reduce((filesToLoad: Promise[], file) => { + const ext = extname(file); + + if (ext === '.css') filesToLoad.push(loadStyle(file)); + else if (ext === '.js') filesToLoad.push(loadScript(file)); + + return filesToLoad; + }, []) + ); export const bufferToUrl = (buffer: Buffer): string => URL.createObjectURL(new Blob([new Uint8Array(buffer)]));