From a82f70ea9f98ed0a602a20f7fe8954f6e4200b25 Mon Sep 17 00:00:00 2001
From: Fabio Alessandrelli <fabio.alessandrelli@gmail.com>
Date: Thu, 19 Nov 2020 16:54:07 +0100
Subject: [HTML5] Libraries refactor for linting.

Initial work to make liniting easier.

This includes:
- Rename http_request.js to library_godot_http_request.js.
- Rename externs.js to engine.externs.js.
- New library_godot_runtime.js (GodotRuntime) wraps around emscripten
  functions.
- Refactor of XMLHttpRequest handler in engine/preloader.js.
- Few fixes to bugs spotted by early stage linting.
---
 platform/javascript/js/engine/engine.externs.js |   3 +
 platform/javascript/js/engine/engine.js         | 278 ++++++++++++++++++++++++
 platform/javascript/js/engine/preloader.js      | 129 +++++++++++
 platform/javascript/js/engine/utils.js          |  57 +++++
 4 files changed, 467 insertions(+)
 create mode 100644 platform/javascript/js/engine/engine.externs.js
 create mode 100644 platform/javascript/js/engine/engine.js
 create mode 100644 platform/javascript/js/engine/preloader.js
 create mode 100644 platform/javascript/js/engine/utils.js

(limited to 'platform/javascript/js/engine')

diff --git a/platform/javascript/js/engine/engine.externs.js b/platform/javascript/js/engine/engine.externs.js
new file mode 100644
index 0000000000..1a94dd15ec
--- /dev/null
+++ b/platform/javascript/js/engine/engine.externs.js
@@ -0,0 +1,3 @@
+var Godot;
+var WebAssembly = {};
+WebAssembly.instantiate = function(buffer, imports) {};
diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js
new file mode 100644
index 0000000000..792ec9cb28
--- /dev/null
+++ b/platform/javascript/js/engine/engine.js
@@ -0,0 +1,278 @@
+const Engine = (function() {
+	var preloader = new Preloader();
+
+	var wasmExt = '.wasm';
+	var unloadAfterInit = true;
+	var loadPath = '';
+	var loadPromise = null;
+	var initPromise = null;
+	var stderr = null;
+	var stdout = null;
+	var progressFunc = null;
+
+	function load(basePath) {
+		if (loadPromise == null) {
+			loadPath = basePath;
+			loadPromise = preloader.loadPromise(basePath + wasmExt);
+			preloader.setProgressFunc(progressFunc);
+			requestAnimationFrame(preloader.animateProgress);
+		}
+		return loadPromise;
+	};
+
+	function unload() {
+		loadPromise = null;
+	};
+
+	/** @constructor */
+	function Engine() { // eslint-disable-line no-shadow
+		this.canvas = null;
+		this.executableName = '';
+		this.rtenv = null;
+		this.customLocale = null;
+		this.resizeCanvasOnStart = false;
+		this.onExecute = null;
+		this.onExit = null;
+		this.persistentPaths = ['/userfs'];
+	};
+
+	Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
+		if (initPromise) {
+			return initPromise;
+		}
+		if (loadPromise == null) {
+			if (!basePath) {
+				initPromise = Promise.reject(new Error("A base path must be provided when calling `init` and the engine is not loaded."));
+				return initPromise;
+			}
+			load(basePath);
+		}
+		var config = {};
+		if (typeof stdout === 'function')
+			config.print = stdout;
+		if (typeof stderr === 'function')
+			config.printErr = stderr;
+		var me = this;
+		initPromise = new Promise(function(resolve, reject) {
+			config['locateFile'] = Utils.createLocateRewrite(loadPath);
+			config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
+			Godot(config).then(function(module) {
+				module['initFS'](me.persistentPaths).then(function(fs_err) {
+					me.rtenv = module;
+					if (unloadAfterInit) {
+						unload();
+					}
+					resolve();
+					config = null;
+				});
+			});
+		});
+		return initPromise;
+	};
+
+	/** @type {function(string, string):Object} */
+	Engine.prototype.preloadFile = function(file, path) {
+		return preloader.preload(file, path);
+	};
+
+	/** @type {function(...string):Object} */
+	Engine.prototype.start = function() {
+		// Start from arguments.
+		var args = [];
+		for (var i = 0; i < arguments.length; i++) {
+			args.push(arguments[i]);
+		}
+		var me = this;
+		return me.init().then(function() {
+			if (!me.rtenv) {
+				return Promise.reject(new Error('The engine must be initialized before it can be started'));
+			}
+
+			if (!(me.canvas instanceof HTMLCanvasElement)) {
+				me.canvas = Utils.findCanvas();
+				if (!me.canvas) {
+					return Promise.reject(new Error('No canvas found in page'));
+				}
+			}
+
+			// Canvas can grab focus on click, or key events won't work.
+			if (me.canvas.tabIndex < 0) {
+				me.canvas.tabIndex = 0;
+			}
+
+			// Disable right-click context menu.
+			me.canvas.addEventListener('contextmenu', function(ev) {
+				ev.preventDefault();
+			}, false);
+
+			// Until context restoration is implemented warn the user of context loss.
+			me.canvas.addEventListener('webglcontextlost', function(ev) {
+				alert("WebGL context lost, please reload the page"); // eslint-disable-line no-alert
+				ev.preventDefault();
+			}, false);
+
+			// Browser locale, or custom one if defined.
+			var locale = me.customLocale;
+			if (!locale) {
+				locale = navigator.languages ? navigator.languages[0] : navigator.language;
+				locale = locale.split('.')[0];
+			}
+			// Emscripten configuration.
+			me.rtenv['thisProgram'] = me.executableName;
+			me.rtenv['noExitRuntime'] = true;
+			// Godot configuration.
+			me.rtenv['initConfig']({
+				'resizeCanvasOnStart': me.resizeCanvasOnStart,
+				'canvas': me.canvas,
+				'locale': locale,
+				'onExecute': function(p_args) {
+					if (me.onExecute) {
+						me.onExecute(p_args);
+						return 0;
+					}
+					return 1;
+				},
+				'onExit': function(p_code) {
+					me.rtenv['deinitFS']();
+					if (me.onExit) {
+						me.onExit(p_code);
+					}
+					me.rtenv = null;
+				},
+			});
+
+			return new Promise(function(resolve, reject) {
+				preloader.preloadedFiles.forEach(function(file) {
+					me.rtenv['copyToFS'](file.path, file.buffer);
+				});
+				preloader.preloadedFiles.length = 0; // Clear memory
+				me.rtenv['callMain'](args);
+				initPromise = null;
+				resolve();
+			});
+		});
+	};
+
+	Engine.prototype.startGame = function(execName, mainPack, extraArgs) {
+		// Start and init with execName as loadPath if not inited.
+		this.executableName = execName;
+		var me = this;
+		return Promise.all([
+			this.init(execName),
+			this.preloadFile(mainPack, mainPack)
+		]).then(function() {
+			var args = ['--main-pack', mainPack];
+			if (extraArgs)
+				args = args.concat(extraArgs);
+			return me.start.apply(me, args);
+		});
+	};
+
+	Engine.prototype.setWebAssemblyFilenameExtension = function(override) {
+		if (String(override).length === 0) {
+			throw new Error('Invalid WebAssembly filename extension override');
+		}
+		wasmExt = String(override);
+	};
+
+	Engine.prototype.setUnloadAfterInit = function(enabled) {
+		unloadAfterInit = enabled;
+	};
+
+	Engine.prototype.setCanvas = function(canvasElem) {
+		this.canvas = canvasElem;
+	};
+
+	Engine.prototype.setCanvasResizedOnStart = function(enabled) {
+		this.resizeCanvasOnStart = enabled;
+	};
+
+	Engine.prototype.setLocale = function(locale) {
+		this.customLocale = locale;
+	};
+
+	Engine.prototype.setExecutableName = function(newName) {
+		this.executableName = newName;
+	};
+
+	Engine.prototype.setProgressFunc = function(func) {
+		progressFunc = func;
+	};
+
+	Engine.prototype.setStdoutFunc = function(func) {
+		var print = function(text) {
+			let msg = text;
+			if (arguments.length > 1) {
+				msg = Array.prototype.slice.call(arguments).join(" ");
+			}
+			func(msg);
+		};
+		if (this.rtenv)
+			this.rtenv.print = print;
+		stdout = print;
+	};
+
+	Engine.prototype.setStderrFunc = function(func) {
+		var printErr = function(text) {
+			let msg = text
+			if (arguments.length > 1) {
+				msg = Array.prototype.slice.call(arguments).join(" ");
+			}
+			func(msg);
+		};
+		if (this.rtenv)
+			this.rtenv.printErr = printErr;
+		stderr = printErr;
+	};
+
+	Engine.prototype.setOnExecute = function(onExecute) {
+		this.onExecute = onExecute;
+	};
+
+	Engine.prototype.setOnExit = function(onExit) {
+		this.onExit = onExit;
+	};
+
+	Engine.prototype.copyToFS = function(path, buffer) {
+		if (this.rtenv == null) {
+			throw new Error("Engine must be inited before copying files");
+		}
+		this.rtenv['copyToFS'](path, buffer);
+	};
+
+	Engine.prototype.setPersistentPaths = function(persistentPaths) {
+		this.persistentPaths = persistentPaths;
+	};
+
+	Engine.prototype.requestQuit = function() {
+		if (this.rtenv) {
+			this.rtenv['request_quit']();
+		}
+	};
+
+	// Closure compiler exported engine methods.
+	/** @export */
+	Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
+	Engine['load'] = load;
+	Engine['unload'] = unload;
+	Engine.prototype['init'] = Engine.prototype.init;
+	Engine.prototype['preloadFile'] = Engine.prototype.preloadFile;
+	Engine.prototype['start'] = Engine.prototype.start;
+	Engine.prototype['startGame'] = Engine.prototype.startGame;
+	Engine.prototype['setWebAssemblyFilenameExtension'] = Engine.prototype.setWebAssemblyFilenameExtension;
+	Engine.prototype['setUnloadAfterInit'] = Engine.prototype.setUnloadAfterInit;
+	Engine.prototype['setCanvas'] = Engine.prototype.setCanvas;
+	Engine.prototype['setCanvasResizedOnStart'] = Engine.prototype.setCanvasResizedOnStart;
+	Engine.prototype['setLocale'] = Engine.prototype.setLocale;
+	Engine.prototype['setExecutableName'] = Engine.prototype.setExecutableName;
+	Engine.prototype['setProgressFunc'] = Engine.prototype.setProgressFunc;
+	Engine.prototype['setStdoutFunc'] = Engine.prototype.setStdoutFunc;
+	Engine.prototype['setStderrFunc'] = Engine.prototype.setStderrFunc;
+	Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute;
+	Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
+	Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
+	Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
+	Engine.prototype['requestQuit'] = Engine.prototype.requestQuit;
+	return Engine;
+})();
+if (typeof window !== 'undefined') window['Engine'] = Engine;
diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js
new file mode 100644
index 0000000000..8641646e6e
--- /dev/null
+++ b/platform/javascript/js/engine/preloader.js
@@ -0,0 +1,129 @@
+var Preloader = /** @constructor */ function() { // eslint-disable-line no-unused-vars
+
+	const loadXHR = function(resolve, reject, file, tracker, attempts) {
+		const xhr = new XMLHttpRequest();
+		tracker[file] = {
+			total: 0,
+			loaded: 0,
+			final: false,
+		};
+		xhr.onerror = function() {
+			if (attempts <= 1) {
+				reject(new Error("Failed loading file '" + file + "'"));
+			} else {
+				setTimeout(function () {
+					loadXHR(resolve, reject, file, tracker, attempts - 1);
+				}, 1000);
+			}
+		};
+		xhr.onabort = function() {
+			tracker[file].final = true;
+			reject(new Error("Loading file '" + file + "' was aborted."));
+		};
+		xhr.onloadstart = function(ev) {
+			tracker[file].total = ev.total;
+			tracker[file].loaded = ev.loaded;
+		};
+		xhr.onprogress = function(ev) {
+			tracker[file].loaded = ev.loaded;
+			tracker[file].total = ev.total;
+		};
+		xhr.onload = function() {
+			if (xhr.status >= 400) {
+				if (xhr.status < 500 || attempts <= 1) {
+					reject(new Error("Failed loading file '" + file + "': " + xhr.statusText));
+					xhr.abort();
+				} else {
+					setTimeout(function () {
+						loadXHR(resolve, reject, file, tracker, attempts - 1);
+					}, 1000);
+				}
+			} else {
+				tracker[file].final = true;
+				resolve(xhr);
+			}
+		};
+		// Make request.
+		xhr.open('GET', file);
+		if (!file.endsWith('.js')) {
+			xhr.responseType = 'arraybuffer';
+		}
+		xhr.send();
+	};
+
+	const DOWNLOAD_ATTEMPTS_MAX = 4;
+	const loadingFiles = {};
+	const lastProgress = { loaded: 0, total: 0 };
+	let progressFunc = null;
+
+	const animateProgress = function() {
+
+		var loaded = 0;
+		var total = 0;
+		var totalIsValid = true;
+		var progressIsFinal = true;
+
+		Object.keys(loadingFiles).forEach(function(file) {
+			const stat = loadingFiles[file];
+			if (!stat.final) {
+				progressIsFinal = false;
+			}
+			if (!totalIsValid || stat.total === 0) {
+				totalIsValid = false;
+				total = 0;
+			} else {
+				total += stat.total;
+			}
+			loaded += stat.loaded;
+		});
+		if (loaded !== lastProgress.loaded || total !== lastProgress.total) {
+			lastProgress.loaded = loaded;
+			lastProgress.total = total;
+			if (typeof progressFunc === 'function')
+				progressFunc(loaded, total);
+		}
+		if (!progressIsFinal)
+			requestAnimationFrame(animateProgress);
+	}
+
+	this.animateProgress = animateProgress;
+
+	this.setProgressFunc = function(callback) {
+		progressFunc = callback;
+	}
+
+
+	this.loadPromise = function(file) {
+		return new Promise(function(resolve, reject) {
+			loadXHR(resolve, reject, file, loadingFiles, DOWNLOAD_ATTEMPTS_MAX);
+		});
+	}
+
+	this.preloadedFiles = [];
+	this.preload = function(pathOrBuffer, destPath) {
+		let buffer = null;
+		if (typeof pathOrBuffer === 'string') {
+			var me = this;
+			return this.loadPromise(pathOrBuffer).then(function(xhr) {
+				me.preloadedFiles.push({
+					path: destPath || pathOrBuffer,
+					buffer: xhr.response
+				});
+				return Promise.resolve();
+			});
+		} else if (pathOrBuffer instanceof ArrayBuffer) {
+			buffer = new Uint8Array(pathOrBuffer);
+		} else if (ArrayBuffer.isView(pathOrBuffer)) {
+			buffer = new Uint8Array(pathOrBuffer.buffer);
+		}
+		if (buffer) {
+			this.preloadedFiles.push({
+				path: destPath,
+				buffer: pathOrBuffer
+			});
+			return Promise.resolve();
+		} else {
+			return Promise.reject(new Error("Invalid object for preloading"));
+		}
+	};
+};
diff --git a/platform/javascript/js/engine/utils.js b/platform/javascript/js/engine/utils.js
new file mode 100644
index 0000000000..fbab9ba9f9
--- /dev/null
+++ b/platform/javascript/js/engine/utils.js
@@ -0,0 +1,57 @@
+var Utils = { // eslint-disable-line no-unused-vars
+
+	createLocateRewrite: function(execName) {
+		function rw(path) {
+			if (path.endsWith('.worker.js')) {
+				return execName + '.worker.js';
+			} else if (path.endsWith('.audio.worklet.js')) {
+				return execName + '.audio.worklet.js';
+			} else if (path.endsWith('.js')) {
+				return execName + '.js';
+			} else if (path.endsWith('.wasm')) {
+				return execName + '.wasm';
+			}
+			return path;
+		}
+		return rw;
+	},
+
+	createInstantiatePromise: function(wasmLoader) {
+		let loader = wasmLoader;
+		function instantiateWasm(imports, onSuccess) {
+			loader.then(function(xhr) {
+				WebAssembly.instantiate(xhr.response, imports).then(function(result) {
+					onSuccess(result['instance'], result['module']);
+				});
+			});
+			loader = null;
+			return {};
+		};
+
+		return instantiateWasm;
+	},
+
+	findCanvas: function() {
+		var nodes = document.getElementsByTagName('canvas');
+		if (nodes.length && nodes[0] instanceof HTMLCanvasElement) {
+			return nodes[0];
+		}
+		return null;
+	},
+
+	isWebGLAvailable: function(majorVersion = 1) {
+
+		var testContext = false;
+		try {
+			var testCanvas = document.createElement('canvas');
+			if (majorVersion === 1) {
+				testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl');
+			} else if (majorVersion === 2) {
+				testContext = testCanvas.getContext('webgl2') || testCanvas.getContext('experimental-webgl2');
+			}
+		} catch (e) {
+			// Not available
+		}
+		return !!testContext;
+	}
+};
-- 
cgit v1.2.3


From 4617a7fa9cea323978f14053ef2726c84e9bd267 Mon Sep 17 00:00:00 2001
From: Fabio Alessandrelli <fabio.alessandrelli@gmail.com>
Date: Mon, 23 Nov 2020 12:13:52 +0100
Subject: [HTML5] Run eslint --fix.

Should I write a poem about this whole new world? ;)
---
 platform/javascript/js/engine/engine.js    | 139 +++++++++++++++--------------
 platform/javascript/js/engine/preloader.js |  66 +++++++-------
 platform/javascript/js/engine/utils.js     |  33 ++++---
 3 files changed, 121 insertions(+), 117 deletions(-)

(limited to 'platform/javascript/js/engine')

diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js
index 792ec9cb28..74153b672a 100644
--- a/platform/javascript/js/engine/engine.js
+++ b/platform/javascript/js/engine/engine.js
@@ -1,14 +1,14 @@
-const Engine = (function() {
-	var preloader = new Preloader();
+const Engine = (function () {
+	const preloader = new Preloader();
 
-	var wasmExt = '.wasm';
-	var unloadAfterInit = true;
-	var loadPath = '';
-	var loadPromise = null;
-	var initPromise = null;
-	var stderr = null;
-	var stdout = null;
-	var progressFunc = null;
+	let wasmExt = '.wasm';
+	let unloadAfterInit = true;
+	let loadPath = '';
+	let loadPromise = null;
+	let initPromise = null;
+	let stderr = null;
+	let stdout = null;
+	let progressFunc = null;
 
 	function load(basePath) {
 		if (loadPromise == null) {
@@ -18,11 +18,11 @@ const Engine = (function() {
 			requestAnimationFrame(preloader.animateProgress);
 		}
 		return loadPromise;
-	};
+	}
 
 	function unload() {
 		loadPromise = null;
-	};
+	}
 
 	/** @constructor */
 	function Engine() { // eslint-disable-line no-shadow
@@ -34,30 +34,32 @@ const Engine = (function() {
 		this.onExecute = null;
 		this.onExit = null;
 		this.persistentPaths = ['/userfs'];
-	};
+	}
 
-	Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
+	Engine.prototype.init = /** @param {string=} basePath */ function (basePath) {
 		if (initPromise) {
 			return initPromise;
 		}
 		if (loadPromise == null) {
 			if (!basePath) {
-				initPromise = Promise.reject(new Error("A base path must be provided when calling `init` and the engine is not loaded."));
+				initPromise = Promise.reject(new Error('A base path must be provided when calling `init` and the engine is not loaded.'));
 				return initPromise;
 			}
 			load(basePath);
 		}
-		var config = {};
-		if (typeof stdout === 'function')
+		let config = {};
+		if (typeof stdout === 'function') {
 			config.print = stdout;
-		if (typeof stderr === 'function')
+		}
+		if (typeof stderr === 'function') {
 			config.printErr = stderr;
-		var me = this;
-		initPromise = new Promise(function(resolve, reject) {
+		}
+		const me = this;
+		initPromise = new Promise(function (resolve, reject) {
 			config['locateFile'] = Utils.createLocateRewrite(loadPath);
 			config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
-			Godot(config).then(function(module) {
-				module['initFS'](me.persistentPaths).then(function(fs_err) {
+			Godot(config).then(function (module) {
+				module['initFS'](me.persistentPaths).then(function (fs_err) {
 					me.rtenv = module;
 					if (unloadAfterInit) {
 						unload();
@@ -71,19 +73,19 @@ const Engine = (function() {
 	};
 
 	/** @type {function(string, string):Object} */
-	Engine.prototype.preloadFile = function(file, path) {
+	Engine.prototype.preloadFile = function (file, path) {
 		return preloader.preload(file, path);
 	};
 
 	/** @type {function(...string):Object} */
-	Engine.prototype.start = function() {
+	Engine.prototype.start = function () {
 		// Start from arguments.
-		var args = [];
-		for (var i = 0; i < arguments.length; i++) {
+		const args = [];
+		for (let i = 0; i < arguments.length; i++) {
 			args.push(arguments[i]);
 		}
-		var me = this;
-		return me.init().then(function() {
+		const me = this;
+		return me.init().then(function () {
 			if (!me.rtenv) {
 				return Promise.reject(new Error('The engine must be initialized before it can be started'));
 			}
@@ -101,18 +103,18 @@ const Engine = (function() {
 			}
 
 			// Disable right-click context menu.
-			me.canvas.addEventListener('contextmenu', function(ev) {
+			me.canvas.addEventListener('contextmenu', function (ev) {
 				ev.preventDefault();
 			}, false);
 
 			// Until context restoration is implemented warn the user of context loss.
-			me.canvas.addEventListener('webglcontextlost', function(ev) {
-				alert("WebGL context lost, please reload the page"); // eslint-disable-line no-alert
+			me.canvas.addEventListener('webglcontextlost', function (ev) {
+				alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert
 				ev.preventDefault();
 			}, false);
 
 			// Browser locale, or custom one if defined.
-			var locale = me.customLocale;
+			let locale = me.customLocale;
 			if (!locale) {
 				locale = navigator.languages ? navigator.languages[0] : navigator.language;
 				locale = locale.split('.')[0];
@@ -125,14 +127,14 @@ const Engine = (function() {
 				'resizeCanvasOnStart': me.resizeCanvasOnStart,
 				'canvas': me.canvas,
 				'locale': locale,
-				'onExecute': function(p_args) {
+				'onExecute': function (p_args) {
 					if (me.onExecute) {
 						me.onExecute(p_args);
 						return 0;
 					}
 					return 1;
 				},
-				'onExit': function(p_code) {
+				'onExit': function (p_code) {
 					me.rtenv['deinitFS']();
 					if (me.onExit) {
 						me.onExit(p_code);
@@ -141,8 +143,8 @@ const Engine = (function() {
 				},
 			});
 
-			return new Promise(function(resolve, reject) {
-				preloader.preloadedFiles.forEach(function(file) {
+			return new Promise(function (resolve, reject) {
+				preloader.preloadedFiles.forEach(function (file) {
 					me.rtenv['copyToFS'](file.path, file.buffer);
 				});
 				preloader.preloadedFiles.length = 0; // Clear memory
@@ -153,98 +155,101 @@ const Engine = (function() {
 		});
 	};
 
-	Engine.prototype.startGame = function(execName, mainPack, extraArgs) {
+	Engine.prototype.startGame = function (execName, mainPack, extraArgs) {
 		// Start and init with execName as loadPath if not inited.
 		this.executableName = execName;
-		var me = this;
+		const me = this;
 		return Promise.all([
 			this.init(execName),
-			this.preloadFile(mainPack, mainPack)
-		]).then(function() {
-			var args = ['--main-pack', mainPack];
-			if (extraArgs)
+			this.preloadFile(mainPack, mainPack),
+		]).then(function () {
+			let args = ['--main-pack', mainPack];
+			if (extraArgs) {
 				args = args.concat(extraArgs);
+			}
 			return me.start.apply(me, args);
 		});
 	};
 
-	Engine.prototype.setWebAssemblyFilenameExtension = function(override) {
+	Engine.prototype.setWebAssemblyFilenameExtension = function (override) {
 		if (String(override).length === 0) {
 			throw new Error('Invalid WebAssembly filename extension override');
 		}
 		wasmExt = String(override);
 	};
 
-	Engine.prototype.setUnloadAfterInit = function(enabled) {
+	Engine.prototype.setUnloadAfterInit = function (enabled) {
 		unloadAfterInit = enabled;
 	};
 
-	Engine.prototype.setCanvas = function(canvasElem) {
+	Engine.prototype.setCanvas = function (canvasElem) {
 		this.canvas = canvasElem;
 	};
 
-	Engine.prototype.setCanvasResizedOnStart = function(enabled) {
+	Engine.prototype.setCanvasResizedOnStart = function (enabled) {
 		this.resizeCanvasOnStart = enabled;
 	};
 
-	Engine.prototype.setLocale = function(locale) {
+	Engine.prototype.setLocale = function (locale) {
 		this.customLocale = locale;
 	};
 
-	Engine.prototype.setExecutableName = function(newName) {
+	Engine.prototype.setExecutableName = function (newName) {
 		this.executableName = newName;
 	};
 
-	Engine.prototype.setProgressFunc = function(func) {
+	Engine.prototype.setProgressFunc = function (func) {
 		progressFunc = func;
 	};
 
-	Engine.prototype.setStdoutFunc = function(func) {
-		var print = function(text) {
+	Engine.prototype.setStdoutFunc = function (func) {
+		const print = function (text) {
 			let msg = text;
 			if (arguments.length > 1) {
-				msg = Array.prototype.slice.call(arguments).join(" ");
+				msg = Array.prototype.slice.call(arguments).join(' ');
 			}
 			func(msg);
 		};
-		if (this.rtenv)
+		if (this.rtenv) {
 			this.rtenv.print = print;
+		}
 		stdout = print;
 	};
 
-	Engine.prototype.setStderrFunc = function(func) {
-		var printErr = function(text) {
-			let msg = text
+	Engine.prototype.setStderrFunc = function (func) {
+		const printErr = function (text) {
+			let msg = text;
 			if (arguments.length > 1) {
-				msg = Array.prototype.slice.call(arguments).join(" ");
+				msg = Array.prototype.slice.call(arguments).join(' ');
 			}
 			func(msg);
 		};
-		if (this.rtenv)
+		if (this.rtenv) {
 			this.rtenv.printErr = printErr;
+		}
 		stderr = printErr;
 	};
 
-	Engine.prototype.setOnExecute = function(onExecute) {
+	Engine.prototype.setOnExecute = function (onExecute) {
 		this.onExecute = onExecute;
 	};
 
-	Engine.prototype.setOnExit = function(onExit) {
+	Engine.prototype.setOnExit = function (onExit) {
 		this.onExit = onExit;
 	};
 
-	Engine.prototype.copyToFS = function(path, buffer) {
+	Engine.prototype.copyToFS = function (path, buffer) {
 		if (this.rtenv == null) {
-			throw new Error("Engine must be inited before copying files");
+			throw new Error('Engine must be inited before copying files');
 		}
 		this.rtenv['copyToFS'](path, buffer);
 	};
 
-	Engine.prototype.setPersistentPaths = function(persistentPaths) {
+	Engine.prototype.setPersistentPaths = function (persistentPaths) {
 		this.persistentPaths = persistentPaths;
 	};
 
-	Engine.prototype.requestQuit = function() {
+	Engine.prototype.requestQuit = function () {
 		if (this.rtenv) {
 			this.rtenv['request_quit']();
 		}
@@ -274,5 +279,7 @@ const Engine = (function() {
 	Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
 	Engine.prototype['requestQuit'] = Engine.prototype.requestQuit;
 	return Engine;
-})();
-if (typeof window !== 'undefined') window['Engine'] = Engine;
+}());
+if (typeof window !== 'undefined') {
+	window['Engine'] = Engine;
+}
diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js
index 8641646e6e..ec34fb93f2 100644
--- a/platform/javascript/js/engine/preloader.js
+++ b/platform/javascript/js/engine/preloader.js
@@ -1,37 +1,36 @@
-var Preloader = /** @constructor */ function() { // eslint-disable-line no-unused-vars
-
-	const loadXHR = function(resolve, reject, file, tracker, attempts) {
+const Preloader = /** @constructor */ function () { // eslint-disable-line no-unused-vars
+	const loadXHR = function (resolve, reject, file, tracker, attempts) {
 		const xhr = new XMLHttpRequest();
 		tracker[file] = {
 			total: 0,
 			loaded: 0,
 			final: false,
 		};
-		xhr.onerror = function() {
+		xhr.onerror = function () {
 			if (attempts <= 1) {
-				reject(new Error("Failed loading file '" + file + "'"));
+				reject(new Error(`Failed loading file '${file}'`));
 			} else {
 				setTimeout(function () {
 					loadXHR(resolve, reject, file, tracker, attempts - 1);
 				}, 1000);
 			}
 		};
-		xhr.onabort = function() {
+		xhr.onabort = function () {
 			tracker[file].final = true;
-			reject(new Error("Loading file '" + file + "' was aborted."));
+			reject(new Error(`Loading file '${file}' was aborted.`));
 		};
-		xhr.onloadstart = function(ev) {
+		xhr.onloadstart = function (ev) {
 			tracker[file].total = ev.total;
 			tracker[file].loaded = ev.loaded;
 		};
-		xhr.onprogress = function(ev) {
+		xhr.onprogress = function (ev) {
 			tracker[file].loaded = ev.loaded;
 			tracker[file].total = ev.total;
 		};
-		xhr.onload = function() {
+		xhr.onload = function () {
 			if (xhr.status >= 400) {
 				if (xhr.status < 500 || attempts <= 1) {
-					reject(new Error("Failed loading file '" + file + "': " + xhr.statusText));
+					reject(new Error(`Failed loading file '${file}': ${xhr.statusText}`));
 					xhr.abort();
 				} else {
 					setTimeout(function () {
@@ -56,14 +55,13 @@ var Preloader = /** @constructor */ function() { // eslint-disable-line no-unuse
 	const lastProgress = { loaded: 0, total: 0 };
 	let progressFunc = null;
 
-	const animateProgress = function() {
-
-		var loaded = 0;
-		var total = 0;
-		var totalIsValid = true;
-		var progressIsFinal = true;
+	const animateProgress = function () {
+		let loaded = 0;
+		let total = 0;
+		let totalIsValid = true;
+		let progressIsFinal = true;
 
-		Object.keys(loadingFiles).forEach(function(file) {
+		Object.keys(loadingFiles).forEach(function (file) {
 			const stat = loadingFiles[file];
 			if (!stat.final) {
 				progressIsFinal = false;
@@ -79,35 +77,36 @@ var Preloader = /** @constructor */ function() { // eslint-disable-line no-unuse
 		if (loaded !== lastProgress.loaded || total !== lastProgress.total) {
 			lastProgress.loaded = loaded;
 			lastProgress.total = total;
-			if (typeof progressFunc === 'function')
+			if (typeof progressFunc === 'function') {
 				progressFunc(loaded, total);
+			}
 		}
-		if (!progressIsFinal)
+		if (!progressIsFinal) {
 			requestAnimationFrame(animateProgress);
-	}
+		}
+	};
 
 	this.animateProgress = animateProgress;
 
-	this.setProgressFunc = function(callback) {
+	this.setProgressFunc = function (callback) {
 		progressFunc = callback;
-	}
-
+	};
 
-	this.loadPromise = function(file) {
-		return new Promise(function(resolve, reject) {
+	this.loadPromise = function (file) {
+		return new Promise(function (resolve, reject) {
 			loadXHR(resolve, reject, file, loadingFiles, DOWNLOAD_ATTEMPTS_MAX);
 		});
-	}
+	};
 
 	this.preloadedFiles = [];
-	this.preload = function(pathOrBuffer, destPath) {
+	this.preload = function (pathOrBuffer, destPath) {
 		let buffer = null;
 		if (typeof pathOrBuffer === 'string') {
-			var me = this;
-			return this.loadPromise(pathOrBuffer).then(function(xhr) {
+			const me = this;
+			return this.loadPromise(pathOrBuffer).then(function (xhr) {
 				me.preloadedFiles.push({
 					path: destPath || pathOrBuffer,
-					buffer: xhr.response
+					buffer: xhr.response,
 				});
 				return Promise.resolve();
 			});
@@ -119,11 +118,10 @@ var Preloader = /** @constructor */ function() { // eslint-disable-line no-unuse
 		if (buffer) {
 			this.preloadedFiles.push({
 				path: destPath,
-				buffer: pathOrBuffer
+				buffer: pathOrBuffer,
 			});
 			return Promise.resolve();
-		} else {
-			return Promise.reject(new Error("Invalid object for preloading"));
 		}
+		return Promise.reject(new Error('Invalid object for preloading'));
 	};
 };
diff --git a/platform/javascript/js/engine/utils.js b/platform/javascript/js/engine/utils.js
index fbab9ba9f9..d0fca4e1cb 100644
--- a/platform/javascript/js/engine/utils.js
+++ b/platform/javascript/js/engine/utils.js
@@ -1,49 +1,48 @@
-var Utils = { // eslint-disable-line no-unused-vars
+const Utils = { // eslint-disable-line no-unused-vars
 
-	createLocateRewrite: function(execName) {
+	createLocateRewrite: function (execName) {
 		function rw(path) {
 			if (path.endsWith('.worker.js')) {
-				return execName + '.worker.js';
+				return `${execName}.worker.js`;
 			} else if (path.endsWith('.audio.worklet.js')) {
-				return execName + '.audio.worklet.js';
+				return `${execName}.audio.worklet.js`;
 			} else if (path.endsWith('.js')) {
-				return execName + '.js';
+				return `${execName}.js`;
 			} else if (path.endsWith('.wasm')) {
-				return execName + '.wasm';
+				return `${execName}.wasm`;
 			}
 			return path;
 		}
 		return rw;
 	},
 
-	createInstantiatePromise: function(wasmLoader) {
+	createInstantiatePromise: function (wasmLoader) {
 		let loader = wasmLoader;
 		function instantiateWasm(imports, onSuccess) {
-			loader.then(function(xhr) {
-				WebAssembly.instantiate(xhr.response, imports).then(function(result) {
+			loader.then(function (xhr) {
+				WebAssembly.instantiate(xhr.response, imports).then(function (result) {
 					onSuccess(result['instance'], result['module']);
 				});
 			});
 			loader = null;
 			return {};
-		};
+		}
 
 		return instantiateWasm;
 	},
 
-	findCanvas: function() {
-		var nodes = document.getElementsByTagName('canvas');
+	findCanvas: function () {
+		const nodes = document.getElementsByTagName('canvas');
 		if (nodes.length && nodes[0] instanceof HTMLCanvasElement) {
 			return nodes[0];
 		}
 		return null;
 	},
 
-	isWebGLAvailable: function(majorVersion = 1) {
-
-		var testContext = false;
+	isWebGLAvailable: function (majorVersion = 1) {
+		let testContext = false;
 		try {
-			var testCanvas = document.createElement('canvas');
+			const testCanvas = document.createElement('canvas');
 			if (majorVersion === 1) {
 				testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl');
 			} else if (majorVersion === 2) {
@@ -53,5 +52,5 @@ var Utils = { // eslint-disable-line no-unused-vars
 			// Not available
 		}
 		return !!testContext;
-	}
+	},
 };
-- 
cgit v1.2.3