UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

105 lines (102 loc) 3.57 kB
import { platform } from '../../core/platform.js'; import { script } from '../script.js'; import { ScriptTypes } from '../script/script-types.js'; import { registerScript } from '../script/script-create.js'; import { ResourceLoader } from './loader.js'; import { ResourceHandler } from './handler.js'; import { Script } from '../script/script.js'; const toLowerCamelCase = (str)=>str[0].toLowerCase() + str.substring(1); class ScriptHandler extends ResourceHandler { constructor(app){ super(app, "script"); this._scripts = {}; this._cache = {}; } clearCache() { for(const key in this._cache){ const element = this._cache[key]; const parent = element.parentNode; if (parent) { parent.removeChild(element); } } this._cache = {}; } load(url, callback) { if (typeof url === 'string') { url = { load: url, original: url }; } const self = this; script.app = this._app; const onScriptLoad = (url.load, (err, url, extra)=>{ if (!err) { const obj = {}; for(let i = 0; i < ScriptTypes._types.length; i++){ obj[ScriptTypes._types[i].name] = ScriptTypes._types[i]; } ScriptTypes._types.length = 0; callback(null, obj, extra); const urlWithoutEndHash = url.split('&hash=')[0]; delete self._loader._cache[ResourceLoader.makeKey(urlWithoutEndHash, "script")]; } else { callback(err); } }); const [basePath] = url.load.split('?'); const isEsmScript = basePath.endsWith('.mjs'); if (isEsmScript) { this._loadModule(basePath, onScriptLoad); } else { this._loadScript(url.load, onScriptLoad); } } open(url, data) { return data; } patch(asset, assets) {} _loadScript(url, callback) { const head = document.head; const element = document.createElement("script"); this._cache[url] = element; element.async = false; element.addEventListener('error', (e)=>{ callback(`Script: ${e.target.src} failed to load`); }, false); let done = false; element.onload = element.onreadystatechange = function() { if (!done && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) { done = true; callback(null, url, element); } }; element.src = url; head.appendChild(element); } _loadModule(url, callback) { const isBrowserWithOrigin = platform.browser && window.location.origin !== 'null'; const baseUrl = isBrowserWithOrigin ? window.location.origin + window.location.pathname : import.meta.url; const importUrl = new URL(url, baseUrl); import(/* @vite-ignore */ /* webpackIgnore: true */ importUrl.toString()).then((module)=>{ const filename = importUrl.pathname.split('/').pop(); const scriptSchema = this._app.assets.find(filename, "script")?.data?.scripts; for(const key in module){ const scriptClass = module[key]; const extendsScriptType = scriptClass.prototype instanceof Script; if (extendsScriptType) { const lowerCamelCaseName = toLowerCamelCase(scriptClass.name); if (!scriptClass.scriptName) ; const scriptName = scriptClass.scriptName ?? lowerCamelCaseName; registerScript(scriptClass, scriptName); if (scriptSchema) this._app.scripts.addSchema(scriptName, scriptSchema[scriptName]); } } callback(null, url, null); }).catch((err)=>{ callback(err); }); } } export { ScriptHandler };