From e4cdae3624248c240b430a1d43c3610e182dab40 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Nov 2020 16:54:07 +0100 Subject: [PATCH 1/3] [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. --- modules/webrtc/library_godot_webrtc.js | 102 +++++++------ modules/websocket/library_godot_websocket.js | 41 +++--- platform/javascript/SCsub | 23 +-- platform/javascript/engine/preloader.js | 139 ------------------ .../engine/engine.externs.js} | 0 platform/javascript/{ => js}/engine/engine.js | 23 ++- platform/javascript/js/engine/preloader.js | 129 ++++++++++++++++ platform/javascript/{ => js}/engine/utils.js | 14 +- .../{native => js/libs}/audio.worklet.js | 24 +-- .../libs}/library_godot_audio.js | 47 +++--- .../libs}/library_godot_display.js | 85 ++++++----- .../libs}/library_godot_editor_tools.js | 7 +- .../{native => js/libs}/library_godot_eval.js | 22 +-- .../libs/library_godot_http_request.js} | 29 ++-- .../{native => js/libs}/library_godot_os.js | 73 +++------ .../js/libs/library_godot_runtime.js | 120 +++++++++++++++ 16 files changed, 483 insertions(+), 395 deletions(-) delete mode 100644 platform/javascript/engine/preloader.js rename platform/javascript/{engine/externs.js => js/engine/engine.externs.js} (100%) rename platform/javascript/{ => js}/engine/engine.js (93%) create mode 100644 platform/javascript/js/engine/preloader.js rename platform/javascript/{ => js}/engine/utils.js (86%) rename platform/javascript/{native => js/libs}/audio.worklet.js (92%) rename platform/javascript/{native => js/libs}/library_godot_audio.js (88%) rename platform/javascript/{native => js/libs}/library_godot_display.js (85%) rename platform/javascript/{native => js/libs}/library_godot_editor_tools.js (95%) rename platform/javascript/{native => js/libs}/library_godot_eval.js (86%) rename platform/javascript/{native/http_request.js => js/libs/library_godot_http_request.js} (83%) rename platform/javascript/{native => js/libs}/library_godot_os.js (83%) create mode 100644 platform/javascript/js/libs/library_godot_runtime.js diff --git a/modules/webrtc/library_godot_webrtc.js b/modules/webrtc/library_godot_webrtc.js index b75996b1f39..c8a10018e58 100644 --- a/modules/webrtc/library_godot_webrtc.js +++ b/modules/webrtc/library_godot_webrtc.js @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -var GodotRTCDataChannel = { +const GodotRTCDataChannel = { // Our socket implementation that forwards events to C++. - $GodotRTCDataChannel__deps: ['$IDHandler', '$GodotOS'], + $GodotRTCDataChannel__deps: ['$IDHandler', '$GodotRuntime'], $GodotRTCDataChannel: { - connect: function(p_id, p_on_open, p_on_message, p_on_error, p_on_close) { const ref = IDHandler.get(p_id); if (!ref) { @@ -55,21 +54,21 @@ var GodotRTCDataChannel = { if (event.data instanceof ArrayBuffer) { buffer = new Uint8Array(event.data); } else if (event.data instanceof Blob) { - console.error("Blob type not supported"); + GodotRuntime.error("Blob type not supported"); return; } else if (typeof event.data === "string") { is_string = 1; var enc = new TextEncoder("utf-8"); buffer = new Uint8Array(enc.encode(event.data)); } else { - console.error("Unknown message type"); + GodotRuntime.error("Unknown message type"); return; } var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = _malloc(len); + var out = GodotRuntime.malloc(len); HEAPU8.set(buffer, out); p_on_message(out, len, is_string); - _free(out); + GodotRuntime.free(out); } }, @@ -105,9 +104,9 @@ var GodotRTCDataChannel = { case "closing": return 2; case "closed": + default: return 3; } - return 3; // CLOSED }, godot_js_rtc_datachannel_send: function(p_id, p_buffer, p_length, p_raw) { @@ -118,7 +117,7 @@ var GodotRTCDataChannel = { const bytes_array = new Uint8Array(p_length); for (var i = 0; i < p_length; i++) { - bytes_array[i] = getValue(p_buffer + i, 'i8'); + bytes_array[i] = GodotRuntime.getHeapValue(p_buffer + i, 'i8'); } if (p_raw) { @@ -127,6 +126,7 @@ var GodotRTCDataChannel = { const string = new TextDecoder('utf-8').decode(bytes_array); ref.send(string); } + return 0; }, godot_js_rtc_datachannel_is_ordered: function(p_id) { @@ -164,7 +164,7 @@ var GodotRTCDataChannel = { if (!ref || !ref.label) { return 0; } - return GodotOS.allocString(ref.label); + return GodotRuntime.allocString(ref.label); }, godot_js_rtc_datachannel_protocol_get: function(p_id) { @@ -172,7 +172,7 @@ var GodotRTCDataChannel = { if (!ref || !ref.protocol) { return 0; } - return GodotOS.allocString(ref.protocol); + return GodotRuntime.allocString(ref.protocol); }, godot_js_rtc_datachannel_destroy: function(p_id) { @@ -181,10 +181,10 @@ var GodotRTCDataChannel = { }, godot_js_rtc_datachannel_connect: function(p_id, p_ref, p_on_open, p_on_message, p_on_error, p_on_close) { - const onopen = GodotOS.get_func(p_on_open).bind(null, p_ref); - const onmessage = GodotOS.get_func(p_on_message).bind(null, p_ref); - const onerror = GodotOS.get_func(p_on_error).bind(null, p_ref); - const onclose = GodotOS.get_func(p_on_close).bind(null, p_ref); + const onopen = GodotRuntime.get_func(p_on_open).bind(null, p_ref); + const onmessage = GodotRuntime.get_func(p_on_message).bind(null, p_ref); + const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_ref); + const onclose = GodotRuntime.get_func(p_on_close).bind(null, p_ref); GodotRTCDataChannel.connect(p_id, onopen, onmessage, onerror, onclose); }, @@ -200,9 +200,8 @@ var GodotRTCDataChannel = { autoAddDeps(GodotRTCDataChannel, '$GodotRTCDataChannel'); mergeInto(LibraryManager.library, GodotRTCDataChannel); -var GodotRTCPeerConnection = { - - $GodotRTCPeerConnection__deps: ['$IDHandler', '$GodotOS', '$GodotRTCDataChannel'], +const GodotRTCPeerConnection = { + $GodotRTCPeerConnection__deps: ['$IDHandler', '$GodotRuntime', '$GodotRTCDataChannel'], $GodotRTCPeerConnection: { onstatechange: function(p_id, p_conn, callback, event) { const ref = IDHandler.get(p_id); @@ -213,17 +212,24 @@ var GodotRTCPeerConnection = { switch(p_conn.iceConnectionState) { case "new": state = 0; + break; case "checking": state = 1; + break; case "connected": case "completed": state = 2; + break; case "disconnected": state = 3; + break; case "failed": state = 4; + break; case "closed": + default: state = 5; + break; } callback(state); }, @@ -235,11 +241,11 @@ var GodotRTCPeerConnection = { } let c = event.candidate; - let candidate_str = GodotOS.allocString(c.candidate); - let mid_str = GodotOS.allocString(c.sdpMid); + let candidate_str = GodotRuntime.allocString(c.candidate); + let mid_str = GodotRuntime.allocString(c.sdpMid); callback(mid_str, c.sdpMLineIndex, candidate_str); - _free(candidate_str); - _free(mid_str); + GodotRuntime.free(candidate_str); + GodotRuntime.free(mid_str); }, ondatachannel: function(p_id, callback, event) { @@ -257,11 +263,11 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - let type_str = GodotOS.allocString(session.type); - let sdp_str = GodotOS.allocString(session.sdp); + let type_str = GodotRuntime.allocString(session.type); + let sdp_str = GodotRuntime.allocString(session.sdp); callback(type_str, sdp_str); - _free(type_str); - _free(sdp_str); + GodotRuntime.free(type_str); + GodotRuntime.free(sdp_str); }, onerror: function(p_id, callback, error) { @@ -269,22 +275,22 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - console.error(error); + GodotRuntime.error(error); callback(); }, }, godot_js_rtc_pc_create: function(p_config, p_ref, p_on_state_change, p_on_candidate, p_on_datachannel) { - const onstatechange = GodotOS.get_func(p_on_state_change).bind(null, p_ref); - const oncandidate = GodotOS.get_func(p_on_candidate).bind(null, p_ref); - const ondatachannel = GodotOS.get_func(p_on_datachannel).bind(null, p_ref); + const onstatechange = GodotRuntime.get_func(p_on_state_change).bind(null, p_ref); + const oncandidate = GodotRuntime.get_func(p_on_candidate).bind(null, p_ref); + const ondatachannel = GodotRuntime.get_func(p_on_datachannel).bind(null, p_ref); - var config = JSON.parse(UTF8ToString(p_config)); + var config = JSON.parse(GodotRuntime.parseString(p_config)); var conn = null; try { conn = new RTCPeerConnection(config); } catch (e) { - console.error(e); + GodotRuntime.error(e); return 0; } @@ -320,8 +326,8 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - const onsession = GodotOS.get_func(p_on_session).bind(null, p_obj); - const onerror = GodotOS.get_func(p_on_error).bind(null, p_obj); + const onsession = GodotRuntime.get_func(p_on_session).bind(null, p_obj); + const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_obj); ref.createOffer().then(function(session) { GodotRTCPeerConnection.onsession(p_id, onsession, session); }).catch(function(error) { @@ -334,9 +340,9 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - const type = UTF8ToString(p_type); - const sdp = UTF8ToString(p_sdp); - const onerror = GodotOS.get_func(p_on_error).bind(null, p_obj); + const type = GodotRuntime.parseString(p_type); + const sdp = GodotRuntime.parseString(p_sdp); + const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_obj); ref.setLocalDescription({ 'sdp': sdp, 'type': type @@ -350,16 +356,16 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - const type = UTF8ToString(p_type); - const sdp = UTF8ToString(p_sdp); - const onerror = GodotOS.get_func(p_on_error).bind(null, p_obj); - const onsession = GodotOS.get_func(p_session_created).bind(null, p_obj); + const type = GodotRuntime.parseString(p_type); + const sdp = GodotRuntime.parseString(p_sdp); + const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_obj); + const onsession = GodotRuntime.get_func(p_session_created).bind(null, p_obj); ref.setRemoteDescription({ 'sdp': sdp, 'type': type }).then(function() { - if (type != 'offer') { - return; + if (type !== 'offer') { + return Promise.resolve(); } return ref.createAnswer().then(function(session) { GodotRTCPeerConnection.onsession(p_id, onsession, session); @@ -374,8 +380,8 @@ var GodotRTCPeerConnection = { if (!ref) { return; } - var sdpMidName = UTF8ToString(p_mid_name); - var sdpName = UTF8ToString(p_sdp); + var sdpMidName = GodotRuntime.parseString(p_mid_name); + var sdpName = GodotRuntime.parseString(p_sdp); ref.addIceCandidate(new RTCIceCandidate({ "candidate": sdpName, "sdpMid": sdpMidName, @@ -391,13 +397,13 @@ var GodotRTCPeerConnection = { return 0; } - const label = UTF8ToString(p_label); - const config = JSON.parse(UTF8ToString(p_config)); + const label = GodotRuntime.parseString(p_label); + const config = JSON.parse(GodotRuntime.parseString(p_config)); const channel = ref.createDataChannel(label, config); return IDHandler.add(channel); } catch (e) { - console.error(e); + GodotRuntime.error(e); return 0; } }, diff --git a/modules/websocket/library_godot_websocket.js b/modules/websocket/library_godot_websocket.js index 2ecb175c51f..0856cb13e62 100644 --- a/modules/websocket/library_godot_websocket.js +++ b/modules/websocket/library_godot_websocket.js @@ -28,10 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -var GodotWebSocket = { - +const GodotWebSocket = { // Our socket implementation that forwards events to C++. - $GodotWebSocket__deps: ['$IDHandler'], + $GodotWebSocket__deps: ['$IDHandler', '$GodotRuntime'], $GodotWebSocket: { // Connection opened, report selected protocol _onopen: function(p_id, callback, event) { @@ -39,9 +38,9 @@ var GodotWebSocket = { if (!ref) { return; // Godot object is gone. } - let c_str = GodotOS.allocString(ref.protocol); + let c_str = GodotRuntime.allocString(ref.protocol); callback(c_str); - _free(c_str); + GodotRuntime.free(c_str); }, // Message received, report content and type (UTF8 vs binary) @@ -55,21 +54,21 @@ var GodotWebSocket = { if (event.data instanceof ArrayBuffer) { buffer = new Uint8Array(event.data); } else if (event.data instanceof Blob) { - alert("Blob type not supported"); + GodotRuntime.error("Blob type not supported"); return; } else if (typeof event.data === "string") { is_string = 1; var enc = new TextEncoder("utf-8"); buffer = new Uint8Array(enc.encode(event.data)); } else { - alert("Unknown message type"); + GodotRuntime.error("Unknown message type"); return; } var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = _malloc(len); + var out = GodotRuntime.malloc(len); HEAPU8.set(buffer, out); callback(out, len, is_string); - _free(out); + GodotRuntime.free(out); }, // An error happened, 'onclose' will be called after this. @@ -87,15 +86,15 @@ var GodotWebSocket = { if (!ref) { return; // Godot object is gone. } - let c_str = GodotOS.allocString(event.reason); + let c_str = GodotRuntime.allocString(event.reason); callback(event.code, c_str, event.wasClean ? 1 : 0); - _free(c_str); + GodotRuntime.free(c_str); }, // Send a message send: function(p_id, p_data) { const ref = IDHandler.get(p_id); - if (!ref || ref.readyState != ref.OPEN) { + if (!ref || ref.readyState !== ref.OPEN) { return 1; // Godot object is gone or socket is not in a ready state. } ref.send(p_data); @@ -116,7 +115,7 @@ var GodotWebSocket = { const ref = IDHandler.get(p_id); if (ref && ref.readyState < ref.CLOSING) { const code = p_code; - const reason = UTF8ToString(p_reason); + const reason = GodotRuntime.parseString(p_reason); ref.close(code, reason); } }, @@ -137,12 +136,12 @@ var GodotWebSocket = { }, godot_js_websocket_create: function(p_ref, p_url, p_proto, p_on_open, p_on_message, p_on_error, p_on_close) { - const on_open = GodotOS.get_func(p_on_open).bind(null, p_ref); - const on_message = GodotOS.get_func(p_on_message).bind(null, p_ref); - const on_error = GodotOS.get_func(p_on_error).bind(null, p_ref); - const on_close = GodotOS.get_func(p_on_close).bind(null, p_ref); - const url = UTF8ToString(p_url); - const protos = UTF8ToString(p_proto); + const on_open = GodotRuntime.get_func(p_on_open).bind(null, p_ref); + const on_message = GodotRuntime.get_func(p_on_message).bind(null, p_ref); + const on_error = GodotRuntime.get_func(p_on_error).bind(null, p_ref); + const on_close = GodotRuntime.get_func(p_on_close).bind(null, p_ref); + const url = GodotRuntime.parseString(p_url); + const protos = GodotRuntime.parseString(p_proto); var socket = null; try { if (protos) { @@ -161,7 +160,7 @@ var GodotWebSocket = { var bytes_array = new Uint8Array(p_buf_len); var i = 0; for(i = 0; i < p_buf_len; i++) { - bytes_array[i] = getValue(p_buf + i, 'i8'); + bytes_array[i] = GodotRuntime.getHeapValue(p_buf + i, 'i8'); } var out = bytes_array.buffer; if (!p_raw) { @@ -172,7 +171,7 @@ var GodotWebSocket = { godot_js_websocket_close: function(p_id, p_code, p_reason) { const code = p_code; - const reason = UTF8ToString(p_reason); + const reason = GodotRuntime.parseString(p_reason); GodotWebSocket.close(p_id, code, reason); }, diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index ae7f4872a5d..c280334c378 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -19,27 +19,28 @@ build = env.add_program(build_targets, javascript_files) env.AddJSLibraries( [ - "native/http_request.js", - "native/library_godot_audio.js", - "native/library_godot_display.js", - "native/library_godot_os.js", + "js/libs/library_godot_audio.js", + "js/libs/library_godot_display.js", + "js/libs/library_godot_http_request.js", + "js/libs/library_godot_os.js", + "js/libs/library_godot_runtime.js", ] ) if env["tools"]: - env.AddJSLibraries(["native/library_godot_editor_tools.js"]) + env.AddJSLibraries(["js/libs/library_godot_editor_tools.js"]) if env["javascript_eval"]: - env.AddJSLibraries(["native/library_godot_eval.js"]) + env.AddJSLibraries(["js/libs/library_godot_eval.js"]) for lib in env["JS_LIBS"]: env.Append(LINKFLAGS=["--js-library", lib]) env.Depends(build, env["JS_LIBS"]) engine = [ - "engine/preloader.js", - "engine/utils.js", - "engine/engine.js", + "js/engine/preloader.js", + "js/engine/utils.js", + "js/engine/engine.js", ] -externs = [env.File("#platform/javascript/engine/externs.js")] +externs = [env.File("#platform/javascript/js/engine/engine.externs.js")] js_engine = env.CreateEngineFile("#bin/godot${PROGSUFFIX}.engine.js", engine, externs) env.Depends(js_engine, externs) @@ -58,7 +59,7 @@ out_files = [ zip_dir.File(binary_name + ".audio.worklet.js"), ] html_file = "#misc/dist/html/editor.html" if env["tools"] else "#misc/dist/html/full-size.html" -in_files = [js_wrapped, build[1], html_file, "#platform/javascript/native/audio.worklet.js"] +in_files = [js_wrapped, build[1], html_file, "#platform/javascript/js/libs/audio.worklet.js"] if env["threads_enabled"]: in_files.append(build[2]) out_files.append(zip_dir.File(binary_name + ".worker.js")) diff --git a/platform/javascript/engine/preloader.js b/platform/javascript/engine/preloader.js deleted file mode 100644 index 17918eae382..00000000000 --- a/platform/javascript/engine/preloader.js +++ /dev/null @@ -1,139 +0,0 @@ -var Preloader = /** @constructor */ function() { - - var DOWNLOAD_ATTEMPTS_MAX = 4; - var progressFunc = null; - var lastProgress = { loaded: 0, total: 0 }; - - var loadingFiles = {}; - this.preloadedFiles = []; - - function loadXHR(resolve, reject, file, tracker) { - var xhr = new XMLHttpRequest; - xhr.open('GET', file); - if (!file.endsWith('.js')) { - xhr.responseType = 'arraybuffer'; - } - ['loadstart', 'progress', 'load', 'error', 'abort'].forEach(function(ev) { - xhr.addEventListener(ev, onXHREvent.bind(xhr, resolve, reject, file, tracker)); - }); - xhr.send(); - } - - function onXHREvent(resolve, reject, file, tracker, ev) { - - if (this.status >= 400) { - - if (this.status < 500 || ++tracker[file].attempts >= DOWNLOAD_ATTEMPTS_MAX) { - reject(new Error("Failed loading file '" + file + "': " + this.statusText)); - this.abort(); - return; - } else { - setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000); - } - } - - switch (ev.type) { - case 'loadstart': - if (tracker[file] === undefined) { - tracker[file] = { - total: ev.total, - loaded: ev.loaded, - attempts: 0, - final: false, - }; - } - break; - - case 'progress': - tracker[file].loaded = ev.loaded; - tracker[file].total = ev.total; - break; - - case 'load': - tracker[file].final = true; - resolve(this); - break; - - case 'error': - if (++tracker[file].attempts >= DOWNLOAD_ATTEMPTS_MAX) { - tracker[file].final = true; - reject(new Error("Failed loading file '" + file + "'")); - } else { - setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000); - } - break; - - case 'abort': - tracker[file].final = true; - reject(new Error("Loading file '" + file + "' was aborted.")); - break; - } - } - - this.loadPromise = function(file) { - return new Promise(function(resolve, reject) { - loadXHR(resolve, reject, file, loadingFiles); - }); - } - - this.preload = function(pathOrBuffer, destPath) { - if (pathOrBuffer instanceof ArrayBuffer) { - pathOrBuffer = new Uint8Array(pathOrBuffer); - } else if (ArrayBuffer.isView(pathOrBuffer)) { - pathOrBuffer = new Uint8Array(pathOrBuffer.buffer); - } - if (pathOrBuffer instanceof Uint8Array) { - this.preloadedFiles.push({ - path: destPath, - buffer: pathOrBuffer - }); - return Promise.resolve(); - } else 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 { - throw Promise.reject("Invalid object for preloading"); - } - }; - - var 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; // Also exposed to start it. - - this.setProgressFunc = function(callback) { - progressFunc = callback; - } -}; diff --git a/platform/javascript/engine/externs.js b/platform/javascript/js/engine/engine.externs.js similarity index 100% rename from platform/javascript/engine/externs.js rename to platform/javascript/js/engine/engine.externs.js diff --git a/platform/javascript/engine/engine.js b/platform/javascript/js/engine/engine.js similarity index 93% rename from platform/javascript/engine/engine.js rename to platform/javascript/js/engine/engine.js index f86e1111fef..e0d20946fc0 100644 --- a/platform/javascript/engine/engine.js +++ b/platform/javascript/js/engine/engine.js @@ -1,4 +1,4 @@ -Function('return this')()['Engine'] = (function() { +const Engine = (function() { var preloader = new Preloader(); var wasmExt = '.wasm'; @@ -25,7 +25,7 @@ Function('return this')()['Engine'] = (function() { }; /** @constructor */ - function Engine() { + function Engine() { // eslint-disable-line no-shadow this.canvas = null; this.executableName = ''; this.rtenv = null; @@ -90,6 +90,9 @@ Function('return this')()['Engine'] = (function() { 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. @@ -104,7 +107,7 @@ Function('return this')()['Engine'] = (function() { // 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"); + alert("WebGL context lost, please reload the page"); // eslint-disable-line no-alert ev.preventDefault(); }, false); @@ -198,10 +201,11 @@ Function('return this')()['Engine'] = (function() { Engine.prototype.setStdoutFunc = function(func) { var print = function(text) { + let msg = text; if (arguments.length > 1) { - text = Array.prototype.slice.call(arguments).join(" "); + msg = Array.prototype.slice.call(arguments).join(" "); } - func(text); + func(msg); }; if (this.rtenv) this.rtenv.print = print; @@ -210,9 +214,11 @@ Function('return this')()['Engine'] = (function() { Engine.prototype.setStderrFunc = function(func) { var printErr = function(text) { - if (arguments.length > 1) - text = Array.prototype.slice.call(arguments).join(" "); - func(text); + let msg = text + if (arguments.length > 1) { + msg = Array.prototype.slice.call(arguments).join(" "); + } + func(msg); }; if (this.rtenv) this.rtenv.printErr = printErr; @@ -269,3 +275,4 @@ Function('return this')()['Engine'] = (function() { 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 00000000000..8641646e6e1 --- /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/engine/utils.js b/platform/javascript/js/engine/utils.js similarity index 86% rename from platform/javascript/engine/utils.js rename to platform/javascript/js/engine/utils.js index 10e3abe91e9..fbab9ba9f90 100644 --- a/platform/javascript/engine/utils.js +++ b/platform/javascript/js/engine/utils.js @@ -1,4 +1,4 @@ -var Utils = { +var Utils = { // eslint-disable-line no-unused-vars createLocateRewrite: function(execName) { function rw(path) { @@ -11,18 +11,20 @@ var Utils = { } else if (path.endsWith('.wasm')) { return execName + '.wasm'; } + return path; } return rw; }, createInstantiatePromise: function(wasmLoader) { + let loader = wasmLoader; function instantiateWasm(imports, onSuccess) { - wasmLoader.then(function(xhr) { + loader.then(function(xhr) { WebAssembly.instantiate(xhr.response, imports).then(function(result) { onSuccess(result['instance'], result['module']); }); }); - wasmLoader = null; + loader = null; return {}; }; @@ -34,7 +36,7 @@ var Utils = { if (nodes.length && nodes[0] instanceof HTMLCanvasElement) { return nodes[0]; } - throw new Error("No canvas found"); + return null; }, isWebGLAvailable: function(majorVersion = 1) { @@ -47,7 +49,9 @@ var Utils = { } else if (majorVersion === 2) { testContext = testCanvas.getContext('webgl2') || testCanvas.getContext('experimental-webgl2'); } - } catch (e) {} + } catch (e) { + // Not available + } return !!testContext; } }; diff --git a/platform/javascript/native/audio.worklet.js b/platform/javascript/js/libs/audio.worklet.js similarity index 92% rename from platform/javascript/native/audio.worklet.js rename to platform/javascript/js/libs/audio.worklet.js index 992ae47fadd..a27035ef224 100644 --- a/platform/javascript/native/audio.worklet.js +++ b/platform/javascript/js/libs/audio.worklet.js @@ -27,8 +27,8 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -class RingBuffer { +class RingBuffer { constructor(p_buffer, p_state) { this.buffer = p_buffer; this.avail = p_state; @@ -105,7 +105,7 @@ class GodotProcessor extends AudioWorkletProcessor { } parse_message(p_cmd, p_data) { - if (p_cmd == "start" && p_data) { + if (p_cmd === "start" && p_data) { const state = p_data[0]; let idx = 0; this.lock = state.subarray(idx, ++idx); @@ -114,14 +114,14 @@ class GodotProcessor extends AudioWorkletProcessor { const avail_out = state.subarray(idx, ++idx); this.input = new RingBuffer(p_data[1], avail_in); this.output = new RingBuffer(p_data[2], avail_out); - } else if (p_cmd == "stop") { + } else if (p_cmd === "stop") { this.runing = false; this.output = null; this.input = null; } } - array_has_data(arr) { + static array_has_data(arr) { return arr.length && arr[0].length && arr[0][0].length; } @@ -132,30 +132,30 @@ class GodotProcessor extends AudioWorkletProcessor { if (this.output === null) { return true; // Not ready yet, keep processing. } - const process_input = this.array_has_data(inputs); + const process_input = GodotProcessor.array_has_data(inputs); if (process_input) { const input = inputs[0]; const chunk = input[0].length * input.length; - if (this.input_buffer.length != chunk) { + if (this.input_buffer.length !== chunk) { this.input_buffer = new Float32Array(chunk); } if (this.input.space_left() >= chunk) { - this.write_input(this.input_buffer, input); + GodotProcessor.write_input(this.input_buffer, input); this.input.write(this.input_buffer); } else { this.port.postMessage("Input buffer is full! Skipping input frame."); } } - const process_output = this.array_has_data(outputs); + const process_output = GodotProcessor.array_has_data(outputs); if (process_output) { const output = outputs[0]; const chunk = output[0].length * output.length; - if (this.output_buffer.length != chunk) { + if (this.output_buffer.length !== chunk) { this.output_buffer = new Float32Array(chunk); } if (this.output.data_left() >= chunk) { this.output.read(this.output_buffer); - this.write_output(output, this.output_buffer); + GodotProcessor.write_output(output, this.output_buffer); } else { this.port.postMessage("Output buffer has not enough frames! Skipping output frame."); } @@ -164,7 +164,7 @@ class GodotProcessor extends AudioWorkletProcessor { return true; } - write_output(dest, source) { + static write_output(dest, source) { const channels = dest.length; for (let ch = 0; ch < channels; ch++) { for (let sample = 0; sample < dest[ch].length; sample++) { @@ -173,7 +173,7 @@ class GodotProcessor extends AudioWorkletProcessor { } } - write_input(dest, source) { + static write_input(dest, source) { const channels = source.length; for (let ch = 0; ch < channels; ch++) { for (let sample = 0; sample < source[ch].length; sample++) { diff --git a/platform/javascript/native/library_godot_audio.js b/platform/javascript/js/libs/library_godot_audio.js similarity index 88% rename from platform/javascript/native/library_godot_audio.js rename to platform/javascript/js/libs/library_godot_audio.js index 846359b8b2e..a657d0a1259 100644 --- a/platform/javascript/native/library_godot_audio.js +++ b/platform/javascript/js/libs/library_godot_audio.js @@ -29,8 +29,7 @@ /*************************************************************************/ const GodotAudio = { - - $GodotAudio__deps: ['$GodotOS'], + $GodotAudio__deps: ['$GodotRuntime', '$GodotOS'], $GodotAudio: { ctx: null, input: null, @@ -43,7 +42,6 @@ const GodotAudio = { // latencyHint: latency / 1000 // Do not specify, leave 'interactive' for good performance. }); GodotAudio.ctx = ctx; - onstatechange(ctx.state); // Immeditately notify state. ctx.onstatechange = function() { let state = 0; switch (ctx.state) { @@ -56,19 +54,22 @@ const GodotAudio = { case 'closed': state = 2; break; + + // no default } onstatechange(state); } + ctx.onstatechange(); // Immeditately notify state. // Update computed latency GodotAudio.interval = setInterval(function() { - let latency = 0; + let computed_latency = 0; if (ctx.baseLatency) { - latency += GodotAudio.ctx.baseLatency; + computed_latency += GodotAudio.ctx.baseLatency; } if (ctx.outputLatency) { - latency += GodotAudio.ctx.outputLatency; + computed_latency += GodotAudio.ctx.outputLatency; } - onlatencyupdate(latency); + onlatencyupdate(computed_latency); }, 1000); GodotOS.atexit(GodotAudio.close_async); return ctx.destination.channelCount; @@ -85,14 +86,14 @@ const GodotAudio = { if (navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ "audio": true - }).then(gotMediaInput, function(e) { out(e) }); + }).then(gotMediaInput, function(e) { GodotRuntime.print(e) }); } else { if (!navigator.getUserMedia) { navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; } navigator.getUserMedia({ "audio": true - }, gotMediaInput, function(e) { out(e) }); + }, gotMediaInput, function(e) { GodotRuntime.print(e) }); } }, @@ -126,7 +127,7 @@ const GodotAudio = { resolve(); }).catch(function(e) { ctx.onstatechange = null; - console.error("Error closing AudioContext", e); + GodotRuntime.error("Error closing AudioContext", e); resolve(); }); }, @@ -141,13 +142,13 @@ const GodotAudio = { }, godot_audio_init: function(p_mix_rate, p_latency, p_state_change, p_latency_update) { - const statechange = GodotOS.get_func(p_state_change); - const latencyupdate = GodotOS.get_func(p_latency_update); + const statechange = GodotRuntime.get_func(p_state_change); + const latencyupdate = GodotRuntime.get_func(p_latency_update); return GodotAudio.init(p_mix_rate, p_latency, statechange, latencyupdate); }, godot_audio_resume: function() { - if (GodotAudio.ctx && GodotAudio.ctx.state != 'running') { + if (GodotAudio.ctx && GodotAudio.ctx.state !== 'running') { GodotAudio.ctx.resume(); } }, @@ -182,14 +183,13 @@ mergeInto(LibraryManager.library, GodotAudio); * The AudioWorklet API driver, used when threads are available. */ const GodotAudioWorklet = { - - $GodotAudioWorklet__deps: ['$GodotAudio'], + $GodotAudioWorklet__deps: ['$GodotAudio', '$GodotConfig'], $GodotAudioWorklet: { promise: null, worklet: null, create: function(channels) { - const path = Module['locateFile']('godot.audio.worklet.js'); + const path = GodotConfig.locate_file('godot.audio.worklet.js'); GodotAudioWorklet.promise = GodotAudio.ctx.audioWorklet.addModule(path).then(function() { GodotAudioWorklet.worklet = new AudioWorkletNode( GodotAudio.ctx, @@ -212,7 +212,7 @@ const GodotAudioWorklet = { 'data': [state, in_buf, out_buf], }); node.port.onmessage = function(event) { - console.error(event.data); + GodotRuntime.error(event.data); }; }); }, @@ -242,9 +242,9 @@ const GodotAudioWorklet = { }, godot_audio_worklet_start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, p_state) { - const out_buffer = GodotOS.heapSub(HEAPF32, p_out_buf, p_out_size); - const in_buffer = GodotOS.heapSub(HEAPF32, p_in_buf, p_in_size); - const state = GodotOS.heapSub(HEAP32, p_state, 4); + const out_buffer = GodotRuntime.heapSub(HEAPF32, p_out_buf, p_out_size); + const in_buffer = GodotRuntime.heapSub(HEAPF32, p_in_buf, p_in_size); + const state = GodotRuntime.heapSub(HEAP32, p_state, 4); GodotAudioWorklet.start(in_buffer, out_buffer, state); }, @@ -269,7 +269,6 @@ mergeInto(LibraryManager.library, GodotAudioWorklet); * The deprecated ScriptProcessorNode API, used when threads are disabled. */ const GodotAudioScript = { - $GodotAudioScript__deps: ['$GodotAudio'], $GodotAudioScript: { script: null, @@ -283,7 +282,7 @@ const GodotAudioScript = { start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, onprocess) { GodotAudioScript.script.onaudioprocess = function(event) { // Read input - const inb = GodotOS.heapSub(HEAPF32, p_in_buf, p_in_size); + const inb = GodotRuntime.heapSub(HEAPF32, p_in_buf, p_in_size); const input = event.inputBuffer; if (GodotAudio.input) { const inlen = input.getChannelData(0).length; @@ -299,7 +298,7 @@ const GodotAudioScript = { onprocess(); // Write the output. - const outb = GodotOS.heapSub(HEAPF32, p_out_buf, p_out_size); + const outb = GodotRuntime.heapSub(HEAPF32, p_out_buf, p_out_size); const output = event.outputBuffer; const channels = output.numberOfChannels; for (let ch = 0; ch < channels; ch++) { @@ -332,7 +331,7 @@ const GodotAudioScript = { }, godot_audio_script_start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, p_cb) { - const onprocess = GodotOS.get_func(p_cb); + const onprocess = GodotRuntime.get_func(p_cb); GodotAudioScript.start(p_in_buf, p_in_size, p_out_buf, p_out_size, onprocess); }, }; diff --git a/platform/javascript/native/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js similarity index 85% rename from platform/javascript/native/library_godot_display.js rename to platform/javascript/js/libs/library_godot_display.js index 490b9181d0b..28f63ba5576 100644 --- a/platform/javascript/native/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -33,13 +33,14 @@ * Keeps track of registered event listeners so it can remove them on shutdown. */ const GodotDisplayListeners = { + $GodotDisplayListeners__deps: ['$GodotOS'], $GodotDisplayListeners__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayListeners.clear(); resolve(); });', $GodotDisplayListeners: { handlers: [], has: function(target, event, method, capture) { return GodotDisplayListeners.handlers.findIndex(function(e) { - return e.target === target && e.event === event && e.method === method && e.capture == capture; + return e.target === target && e.event === event && e.method === method && e.capture === capture; }) !== -1; }, @@ -47,11 +48,11 @@ const GodotDisplayListeners = { if (GodotDisplayListeners.has(target, event, method, capture)) { return; } - function Handler(target, event, method, capture) { - this.target = target; - this.event = event; - this.method = method; - this.capture = capture; + function Handler(p_target, p_event, p_method, p_capture) { + this.target = p_target; + this.event = p_event; + this.method = p_method; + this.capture = p_capture; }; GodotDisplayListeners.handlers.push(new Handler(target, event, method, capture)); target.addEventListener(event, method, capture); @@ -78,7 +79,6 @@ mergeInto(LibraryManager.library, GodotDisplayListeners); * deferred callbacks won't be able to access the files. */ const GodotDisplayDragDrop = { - $GodotDisplayDragDrop__deps: ['$FS', '$GodotFS'], $GodotDisplayDragDrop: { promises: [], @@ -90,7 +90,7 @@ const GodotDisplayDragDrop = { } else if (entry.isFile) { GodotDisplayDragDrop.add_file(entry); } else { - console.error("Unrecognized entry...", entry); + GodotRuntime.error("Unrecognized entry...", entry); } }, @@ -125,19 +125,19 @@ const GodotDisplayDragDrop = { resolve() }; reader.onerror = function() { - console.log("Error reading file"); + GodotRuntime.print("Error reading file"); reject(); } reader.readAsArrayBuffer(file); }, function(err) { - console.log("Error!"); + GodotRuntime.print("Error!"); reject(); }); })); }, process: function(resolve, reject) { - if (GodotDisplayDragDrop.promises.length == 0) { + if (GodotDisplayDragDrop.promises.length === 0) { resolve(); return; } @@ -165,10 +165,10 @@ const GodotDisplayDragDrop = { } } } else { - console.error("File upload not supported"); + GodotRuntime.error("File upload not supported"); } new Promise(GodotDisplayDragDrop.process).then(function() { - const DROP = "/tmp/drop-" + parseInt(Math.random() * Math.pow(2, 31)) + "/"; + const DROP = "/tmp/drop-" + parseInt(Math.random() * (1 << 30), 10) + "/"; const drops = []; const files = []; FS.mkdir(DROP); @@ -176,14 +176,14 @@ const GodotDisplayDragDrop = { const path = elem['path']; GodotFS.copy_to_fs(DROP + path, elem['data']); let idx = path.indexOf("/"); - if (idx == -1) { + if (idx === -1) { // Root file drops.push(DROP + path); } else { // Subdir const sub = path.substr(0, idx); idx = sub.indexOf("/"); - if (idx < 0 && drops.indexOf(DROP + sub) == -1) { + if (idx < 0 && drops.indexOf(DROP + sub) === -1) { drops.push(DROP + sub); } } @@ -200,7 +200,7 @@ const GodotDisplayDragDrop = { let idx = dir.lastIndexOf("/"); while (idx > 0) { dir = dir.substr(0, idx); - if (dirs.indexOf(DROP + dir) == -1) { + if (dirs.indexOf(DROP + dir) === -1) { dirs.push(DROP + dir); } idx = dir.lastIndexOf("/"); @@ -235,8 +235,8 @@ mergeInto(LibraryManager.library, GodotDisplayDragDrop); * Keeps track of cursor status and custom shapes. */ const GodotDisplayCursor = { + $GodotDisplayCursor__deps: ['$GodotOS', '$GodotConfig'], $GodotDisplayCursor__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayCursor.clear(); resolve(); });', - $GodotDisplayCursor__deps: ['$GodotConfig', '$GodotOS'], $GodotDisplayCursor: { shape: 'auto', visible: true, @@ -274,7 +274,7 @@ mergeInto(LibraryManager.library, GodotDisplayCursor); * Exposes all the functions needed by DisplayServer implementation. */ const GodotDisplay = { - $GodotDisplay__deps: ['$GodotConfig', '$GodotOS', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop'], + $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop'], $GodotDisplay: { window_icon: '', }, @@ -289,7 +289,7 @@ const GodotDisplay = { }, godot_js_display_alert: function(p_text) { - window.alert(UTF8ToString(p_text)); + window.alert(GodotRuntime.parseString(p_text)); // eslint-disable-line no-alert }, godot_js_display_pixel_ratio_get: function() { @@ -304,13 +304,13 @@ const GodotDisplay = { }, godot_js_display_canvas_is_focused: function() { - return document.activeElement == GodotConfig.canvas; + return document.activeElement === GodotConfig.canvas; }, godot_js_display_canvas_bounding_rect_position_get: function(r_x, r_y) { const brect = GodotConfig.canvas.getBoundingClientRect(); - setValue(r_x, brect.x, 'i32'); - setValue(r_y, brect.y, 'i32'); + GodotRuntime.setHeapValue(r_x, brect.x, 'i32'); + GodotRuntime.setHeapValue(r_y, brect.y, 'i32'); }, /* @@ -324,25 +324,24 @@ const GodotDisplay = { * Clipboard */ godot_js_display_clipboard_set: function(p_text) { - const text = UTF8ToString(p_text); + const text = GodotRuntime.parseString(p_text); if (!navigator.clipboard || !navigator.clipboard.writeText) { return 1; } navigator.clipboard.writeText(text).catch(function(e) { // Setting OS clipboard is only possible from an input callback. - console.error("Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:", e); + GodotRuntime.error("Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:", e); }); return 0; }, - godot_js_display_clipboard_get_deps: ['$GodotOS'], godot_js_display_clipboard_get: function(callback) { - const func = GodotOS.get_func(callback); + const func = GodotRuntime.get_func(callback); try { navigator.clipboard.readText().then(function (result) { - const ptr = allocate(intArrayFromString(result), ALLOC_NORMAL); + const ptr = GodotRuntime.allocString(result); func(ptr); - _free(ptr); + GodotRuntime.free(ptr); }).catch(function (e) { // Fail graciously. }); @@ -363,7 +362,7 @@ const GodotDisplay = { }, godot_js_display_window_title_set: function(p_data) { - document.title = UTF8ToString(p_data); + document.title = GodotRuntime.parseString(p_data); }, godot_js_display_window_icon_set: function(p_ptr, p_len) { @@ -375,7 +374,7 @@ const GodotDisplay = { document.head.appendChild(link); } const old_icon = GodotDisplay.window_icon; - const png = new Blob([GodotOS.heapCopy(HEAPU8, p_ptr, p_len)], { type: "image/png" }); + const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: "image/png" }); GodotDisplay.window_icon = URL.createObjectURL(png); link.href = GodotDisplay.window_icon; if (old_icon) { @@ -387,8 +386,8 @@ const GodotDisplay = { * Cursor */ godot_js_display_cursor_set_visible: function(p_visible) { - const visible = p_visible != 0; - if (visible == GodotDisplayCursor.visible) { + const visible = p_visible !== 0; + if (visible === GodotDisplayCursor.visible) { return; } GodotDisplayCursor.visible = visible; @@ -404,14 +403,14 @@ const GodotDisplay = { }, godot_js_display_cursor_set_shape: function(p_string) { - GodotDisplayCursor.set_shape(UTF8ToString(p_string)); + GodotDisplayCursor.set_shape(GodotRuntime.parseString(p_string)); }, godot_js_display_cursor_set_custom_shape: function(p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) { - const shape = UTF8ToString(p_shape); + const shape = GodotRuntime.parseString(p_shape); const old_shape = GodotDisplayCursor.cursors[shape]; if (p_len > 0) { - const png = new Blob([GodotOS.heapCopy(HEAPU8, p_ptr, p_len)], { type: 'image/png' }); + const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: 'image/png' }); const url = URL.createObjectURL(png); GodotDisplayCursor.cursors[shape] = { url: url, @@ -421,7 +420,7 @@ const GodotDisplay = { } else { delete GodotDisplayCursor.cursors[shape]; } - if (shape == GodotDisplayCursor.shape) { + if (shape === GodotDisplayCursor.shape) { GodotDisplayCursor.set_shape(GodotDisplayCursor.shape); } if (old_shape) { @@ -434,7 +433,7 @@ const GodotDisplay = { */ godot_js_display_notification_cb: function(callback, p_enter, p_exit, p_in, p_out) { const canvas = GodotConfig.canvas; - const func = GodotOS.get_func(callback); + const func = GodotRuntime.get_func(callback); const notif = [p_enter, p_exit, p_in, p_out]; ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function(evt_name, idx) { GodotDisplayListeners.add(canvas, evt_name, function() { @@ -444,26 +443,26 @@ const GodotDisplay = { }, godot_js_display_paste_cb: function(callback) { - const func = GodotOS.get_func(callback); + const func = GodotRuntime.get_func(callback); GodotDisplayListeners.add(window, 'paste', function(evt) { const text = evt.clipboardData.getData('text'); - const ptr = allocate(intArrayFromString(text), ALLOC_NORMAL); + const ptr = GodotRuntime.allocString(text); func(ptr); - _free(ptr); + GodotRuntime.free(ptr); }, false); }, godot_js_display_drop_files_cb: function(callback) { - const func = GodotOS.get_func(callback) + const func = GodotRuntime.get_func(callback) const dropFiles = function(files) { const args = files || []; if (!args.length) { return; } const argc = args.length; - const argv = GodotOS.allocStringArray(args); + const argv = GodotRuntime.allocStringArray(args); func(argv, argc); - GodotOS.freeStringArray(argv, argc); + GodotRuntime.freeStringArray(argv, argc); }; const canvas = GodotConfig.canvas; GodotDisplayListeners.add(canvas, 'dragover', function(ev) { diff --git a/platform/javascript/native/library_godot_editor_tools.js b/platform/javascript/js/libs/library_godot_editor_tools.js similarity index 95% rename from platform/javascript/native/library_godot_editor_tools.js rename to platform/javascript/js/libs/library_godot_editor_tools.js index bd62bbf4e1f..21e40185aea 100644 --- a/platform/javascript/native/library_godot_editor_tools.js +++ b/platform/javascript/js/libs/library_godot_editor_tools.js @@ -29,12 +29,11 @@ /*************************************************************************/ const GodotEditorTools = { - godot_js_editor_download_file__deps: ['$FS'], godot_js_editor_download_file: function(p_path, p_name, p_mime) { - const path = UTF8ToString(p_path); - const name = UTF8ToString(p_name); - const mime = UTF8ToString(p_mime); + const path = GodotRuntime.parseString(p_path); + const name = GodotRuntime.parseString(p_name); + const mime = GodotRuntime.parseString(p_mime); const size = FS.stat(path)['size']; const buf = new Uint8Array(size); const fd = FS.open(path, 'r'); diff --git a/platform/javascript/native/library_godot_eval.js b/platform/javascript/js/libs/library_godot_eval.js similarity index 86% rename from platform/javascript/native/library_godot_eval.js rename to platform/javascript/js/libs/library_godot_eval.js index e83c61dd9dc..4064938d3e9 100644 --- a/platform/javascript/native/library_godot_eval.js +++ b/platform/javascript/js/libs/library_godot_eval.js @@ -29,36 +29,34 @@ /*************************************************************************/ const GodotEval = { - - godot_js_eval__deps: ['$GodotOS'], + godot_js_eval__deps: ['$GodotRuntime'], godot_js_eval: function(p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) { - const js_code = UTF8ToString(p_js); + const js_code = GodotRuntime.parseString(p_js); let eval_ret = null; try { if (p_use_global_ctx) { // indirect eval call grants global execution context - const global_eval = eval; + const global_eval = eval; // eslint-disable-line no-eval eval_ret = global_eval(js_code); } else { - eval_ret = eval(js_code); + eval_ret = eval(js_code); // eslint-disable-line no-eval } } catch (e) { - err(e); + GodotRuntime.error(e); } switch (typeof eval_ret) { case 'boolean': - setValue(p_union_ptr, eval_ret, 'i32'); + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); return 1; // BOOL case 'number': - setValue(p_union_ptr, eval_ret, 'double'); + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double'); return 3; // REAL case 'string': - let array_ptr = GodotOS.allocString(eval_ret); - setValue(p_union_ptr, array_ptr , '*'); + GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*'); return 4; // STRING case 'object': @@ -73,12 +71,14 @@ const GodotEval = { eval_ret = new Uint8Array(eval_ret); } if (eval_ret instanceof Uint8Array) { - const func = GodotOS.get_func(p_callback); + const func = GodotRuntime.get_func(p_callback); const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length); HEAPU8.set(eval_ret, bytes_ptr); return 20; // POOL_BYTE_ARRAY } break; + + // no default } return 0; // NIL }, diff --git a/platform/javascript/native/http_request.js b/platform/javascript/js/libs/library_godot_http_request.js similarity index 83% rename from platform/javascript/native/http_request.js rename to platform/javascript/js/libs/library_godot_http_request.js index f621689f9de..6f80f3b9580 100644 --- a/platform/javascript/native/http_request.js +++ b/platform/javascript/js/libs/library_godot_http_request.js @@ -27,10 +27,10 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -var GodotHTTPRequest = { +const GodotHTTPRequest = { + $GodotHTTPRequest__deps: ['$GodotRuntime'], $GodotHTTPRequest: { - requests: [], getUnusedRequestId: function() { @@ -67,14 +67,14 @@ var GodotHTTPRequest = { GodotHTTPRequest.requests[xhrId] = null; }, - godot_xhr_open: function(xhrId, method, url, user, password) { - user = user > 0 ? UTF8ToString(user) : null; - password = password > 0 ? UTF8ToString(password) : null; - GodotHTTPRequest.requests[xhrId].open(UTF8ToString(method), UTF8ToString(url), true, user, password); + godot_xhr_open: function(xhrId, method, url, p_user, p_password) { + const user = p_user > 0 ? GodotRuntime.parseString(p_user) : null; + const password = p_password > 0 ? GodotRuntime.parseString(p_password) : null; + GodotHTTPRequest.requests[xhrId].open(GodotRuntime.parseString(method), GodotRuntime.parseString(url), true, user, password); }, godot_xhr_set_request_header: function(xhrId, header, value) { - GodotHTTPRequest.requests[xhrId].setRequestHeader(UTF8ToString(header), UTF8ToString(value)); + GodotHTTPRequest.requests[xhrId].setRequestHeader(GodotRuntime.parseString(header), GodotRuntime.parseString(value)); }, godot_xhr_send_null: function(xhrId) { @@ -83,19 +83,19 @@ var GodotHTTPRequest = { godot_xhr_send_string: function(xhrId, strPtr) { if (!strPtr) { - err("Failed to send string per XHR: null pointer"); + GodotRuntime.error("Failed to send string per XHR: null pointer"); return; } - GodotHTTPRequest.requests[xhrId].send(UTF8ToString(strPtr)); + GodotHTTPRequest.requests[xhrId].send(GodotRuntime.parseString(strPtr)); }, godot_xhr_send_data: function(xhrId, ptr, len) { if (!ptr) { - err("Failed to send data per XHR: null pointer"); + GodotRuntime.error("Failed to send data per XHR: null pointer"); return; } if (len < 0) { - err("Failed to send data per XHR: buffer length less than 0"); + GodotRuntime.error("Failed to send data per XHR: buffer length less than 0"); return; } GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len)); @@ -115,17 +115,14 @@ var GodotHTTPRequest = { godot_xhr_get_response_headers_length: function(xhrId) { var headers = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); - return headers === null ? 0 : lengthBytesUTF8(headers); + return headers === null ? 0 : GodotRuntime.strlen(headers); }, godot_xhr_get_response_headers: function(xhrId, dst, len) { var str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); if (str === null) return; - var buf = new Uint8Array(len + 1); - stringToUTF8Array(str, buf, 0, buf.length); - buf = buf.subarray(0, -1); - HEAPU8.set(buf, dst); + GodotRuntime.stringToHeap(str, dst, len); }, godot_xhr_get_response_length: function(xhrId) { diff --git a/platform/javascript/native/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js similarity index 83% rename from platform/javascript/native/library_godot_os.js rename to platform/javascript/js/libs/library_godot_os.js index ed48280674f..582f04cb1b2 100644 --- a/platform/javascript/native/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -53,8 +53,8 @@ autoAddDeps(IDHandler, "$IDHandler"); mergeInto(LibraryManager.library, IDHandler); const GodotConfig = { - $GodotConfig__postset: 'Module["initConfig"] = GodotConfig.init_config;', + $GodotConfig__deps: ['$GodotRuntime'], $GodotConfig: { canvas: null, locale: "en", @@ -67,16 +67,20 @@ const GodotConfig = { GodotConfig.locale = p_opts['locale'] || GodotConfig.locale; GodotConfig.on_execute = p_opts['onExecute']; // This is called by emscripten, even if undocumented. - Module['onExit'] = p_opts['onExit']; + Module['onExit'] = p_opts['onExit']; // eslint-disable-line no-undef + }, + + locate_file: function(file) { + return Module["locateFile"](file); // eslint-disable-line no-undef }, }, godot_js_config_canvas_id_get: function(p_ptr, p_ptr_max) { - stringToUTF8('#' + GodotConfig.canvas.id, p_ptr, p_ptr_max); + GodotRuntime.stringToHeap('#' + GodotConfig.canvas.id, p_ptr, p_ptr_max); }, godot_js_config_locale_get: function(p_ptr, p_ptr_max) { - stringToUTF8(GodotConfig.locale, p_ptr, p_ptr_max); + GodotRuntime.stringToHeap(GodotConfig.locale, p_ptr, p_ptr_max); }, godot_js_config_is_resize_on_start: function() { @@ -87,8 +91,9 @@ const GodotConfig = { autoAddDeps(GodotConfig, '$GodotConfig'); mergeInto(LibraryManager.library, GodotConfig); + const GodotFS = { - $GodotFS__deps: ['$FS', '$IDBFS'], + $GodotFS__deps: ['$FS', '$IDBFS', '$GodotRuntime'], $GodotFS__postset: [ 'Module["initFS"] = GodotFS.init;', 'Module["deinitFS"] = GodotFS.deinit;', @@ -137,7 +142,7 @@ const GodotFS = { if (err) { GodotFS._mount_points = []; GodotFS._idbfs = false; - console.log("IndexedDB not available: " + err.message); + GodotRuntime.print("IndexedDB not available: " + err.message); } else { GodotFS._idbfs = true; } @@ -152,7 +157,7 @@ const GodotFS = { try { FS.unmount(path); } catch (e) { - console.log("Already unmounted", e); + GodotRuntime.print("Already unmounted", e); } if (GodotFS._idbfs && IDBFS.dbs[path]) { IDBFS.dbs[path].close(); @@ -166,14 +171,14 @@ const GodotFS = { sync: function() { if (GodotFS._syncing) { - err('Already syncing!'); + GodotRuntime.error('Already syncing!'); return Promise.resolve(); } GodotFS._syncing = true; return new Promise(function (resolve, reject) { FS.syncfs(false, function(error) { if (error) { - err('Failed to save IDB file system: ' + error.message); + GodotRuntime.error('Failed to save IDB file system: ' + error.message); } GodotFS._syncing = false; resolve(error); @@ -203,21 +208,16 @@ const GodotFS = { mergeInto(LibraryManager.library, GodotFS); const GodotOS = { - $GodotOS__deps: ['$GodotFS'], + $GodotOS__deps: ['$GodotFS', '$GodotRuntime'], $GodotOS__postset: [ 'Module["request_quit"] = function() { GodotOS.request_quit() };', 'GodotOS._fs_sync_promise = Promise.resolve();', ].join(''), $GodotOS: { - request_quit: function() {}, _async_cbs: [], _fs_sync_promise: null, - get_func: function(ptr) { - return wasmTable.get(ptr); - }, - atexit: function(p_promise_cb) { GodotOS._async_cbs.push(p_promise_cb); }, @@ -238,48 +238,15 @@ const GodotOS = { }, 0); }); }, - - allocString: function(p_str) { - const length = lengthBytesUTF8(p_str)+1; - const c_str = _malloc(length); - stringToUTF8(p_str, c_str, length); - return c_str; - }, - - allocStringArray: function(strings) { - const size = strings.length; - const c_ptr = _malloc(size * 4); - for (let i = 0; i < size; i++) { - HEAP32[(c_ptr >> 2) + i] = GodotOS.allocString(strings[i]); - } - return c_ptr; - }, - - freeStringArray: function(c_ptr, size) { - for (let i = 0; i < size; i++) { - _free(HEAP32[(c_ptr >> 2) + i]); - } - _free(c_ptr); - }, - - heapSub: function(heap, ptr, size) { - const bytes = heap.BYTES_PER_ELEMENT; - return heap.subarray(ptr / bytes, ptr / bytes + size); - }, - - heapCopy: function(heap, ptr, size) { - const bytes = heap.BYTES_PER_ELEMENT; - return heap.slice(ptr / bytes, ptr / bytes + size); - }, }, godot_js_os_finish_async: function(p_callback) { - const func = GodotOS.get_func(p_callback); + const func = GodotRuntime.get_func(p_callback); GodotOS.finish_async(func); }, godot_js_os_request_quit_cb: function(p_callback) { - GodotOS.request_quit = GodotOS.get_func(p_callback); + GodotOS.request_quit = GodotRuntime.get_func(p_callback); }, godot_js_os_fs_is_persistent: function() { @@ -287,7 +254,7 @@ const GodotOS = { }, godot_js_os_fs_sync: function(callback) { - const func = GodotOS.get_func(callback); + const func = GodotRuntime.get_func(callback); GodotOS._fs_sync_promise = GodotFS.sync(); GodotOS._fs_sync_promise.then(function(err) { func(); @@ -295,7 +262,7 @@ const GodotOS = { }, godot_js_os_execute: function(p_json) { - const json_args = UTF8ToString(p_json); + const json_args = GodotRuntime.parseString(p_json); const args = JSON.parse(json_args); if (GodotConfig.on_execute) { GodotConfig.on_execute(args); @@ -305,7 +272,7 @@ const GodotOS = { }, godot_js_os_shell_open: function(p_uri) { - window.open(UTF8ToString(p_uri), '_blank'); + window.open(GodotRuntime.parseString(p_uri), '_blank'); }, }; diff --git a/platform/javascript/js/libs/library_godot_runtime.js b/platform/javascript/js/libs/library_godot_runtime.js new file mode 100644 index 00000000000..1769f83623e --- /dev/null +++ b/platform/javascript/js/libs/library_godot_runtime.js @@ -0,0 +1,120 @@ +/*************************************************************************/ +/* library_godot_runtime.js */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +const GodotRuntime = { + $GodotRuntime: { + /* + * Functions + */ + get_func: function(ptr) { + return wasmTable.get(ptr); // eslint-disable-line no-undef + }, + + /* + * Prints + */ + error: function() { + err.apply(null, Array.from(arguments)); // eslint-disable-line no-undef + }, + + print: function() { + out.apply(null, Array.from(arguments)); // eslint-disable-line no-undef + }, + + /* + * Memory + */ + malloc: function(p_size) { + return _malloc(p_size); // eslint-disable-line no-undef + }, + + free: function(p_ptr) { + _free(p_ptr); // eslint-disable-line no-undef + }, + + getHeapValue: function (p_ptr, p_type) { + return getValue(p_ptr, p_type); // eslint-disable-line no-undef + }, + + setHeapValue: function(p_ptr, p_value, p_type) { + setValue(p_ptr, p_value, p_type); // eslint-disable-line no-undef + }, + + heapSub: function(p_heap, p_ptr, p_len) { + const bytes = p_heap.BYTES_PER_ELEMENT; + return p_heap.subarray(p_ptr / bytes, p_ptr / bytes + p_len); + }, + + heapCopy: function(p_heap, p_ptr, p_len) { + const bytes = p_heap.BYTES_PER_ELEMENT; + return p_heap.slice(p_ptr / bytes, p_ptr / bytes + p_len); + }, + + /* + * Strings + */ + parseString: function(p_ptr) { + return UTF8ToString(p_ptr); // eslint-disable-line no-undef + }, + + strlen: function(p_str) { + return lengthBytesUTF8(p_str); // eslint-disable-line no-undef + }, + + allocString: function(p_str) { + const length = GodotRuntime.strlen(p_str)+1; + const c_str = GodotRuntime.malloc(length); + stringToUTF8(p_str, c_str, length); // eslint-disable-line no-undef + return c_str; + }, + + allocStringArray: function(p_strings) { + const size = p_strings.length; + const c_ptr = GodotRuntime.malloc(size * 4); + for (let i = 0; i < size; i++) { + HEAP32[(c_ptr >> 2) + i] = GodotRuntime.allocString(p_strings[i]); + } + return c_ptr; + }, + + freeStringArray: function(p_ptr, p_len) { + for (let i = 0; i < p_len; i++) { + GodotRuntime.free(HEAP32[(p_ptr >> 2) + i]); + } + GodotRuntime.free(p_ptr); + }, + + stringToHeap: function (p_str, p_ptr, p_len) { + return stringToUTF8Array(p_str, HEAP8, p_ptr, p_len); // eslint-disable-line no-undef + }, + }, +}; +autoAddDeps(GodotRuntime, "$GodotRuntime"); +mergeInto(LibraryManager.library, GodotRuntime); From 0813008b8a47fcc814b968c83d2e5cec45c95207 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Nov 2020 05:59:12 +0100 Subject: [PATCH 2/3] [HTML5] Enforce JavaScript style with eslint. Applies to javascript files inside the platform library folder, the exposed Engine code, and any javascript files in modules. Files ending with ".externs.js" will be ignored, you can create a ".eslintignore" file to specify extra files to be ignored. --- .github/workflows/static_checks.yml | 8 +- platform/javascript/.eslintrc.engine.js | 10 + platform/javascript/.eslintrc.js | 43 + platform/javascript/.eslintrc.libs.js | 22 + platform/javascript/package-lock.json | 1605 +++++++++++++++++++++++ platform/javascript/package.json | 24 + 6 files changed, 1711 insertions(+), 1 deletion(-) create mode 100644 platform/javascript/.eslintrc.engine.js create mode 100644 platform/javascript/.eslintrc.js create mode 100644 platform/javascript/.eslintrc.libs.js create mode 100644 platform/javascript/package-lock.json create mode 100644 platform/javascript/package.json diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index 3fa759bb03c..da3327246ba 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -9,7 +9,7 @@ jobs: - name: Checkout uses: actions/checkout@v2 - # Azure repositories are not reliable, we need to prevent azure giving us packages. + # Azure repositories are not reliable, we need to prevent Azure giving us packages. - name: Make apt sources.list use the default Ubuntu repositories run: | sudo rm -f /etc/apt/sources.list.d/* @@ -33,6 +33,12 @@ jobs: run: | bash ./misc/scripts/black_format.sh + - name: JavaScript style checks via ESLint + run: | + cd platform/javascript + npm ci + npm run lint + - name: Documentation checks run: | doc/tools/makerst.py --dry-run doc/classes modules diff --git a/platform/javascript/.eslintrc.engine.js b/platform/javascript/.eslintrc.engine.js new file mode 100644 index 00000000000..00f0f147a94 --- /dev/null +++ b/platform/javascript/.eslintrc.engine.js @@ -0,0 +1,10 @@ +module.exports = { + "extends": [ + "./.eslintrc.js", + ], + "globals": { + "Godot": true, + "Preloader": true, + "Utils": true, + }, +}; diff --git a/platform/javascript/.eslintrc.js b/platform/javascript/.eslintrc.js new file mode 100644 index 00000000000..0ff9d67d266 --- /dev/null +++ b/platform/javascript/.eslintrc.js @@ -0,0 +1,43 @@ +module.exports = { + "env": { + "browser": true, + "es2021": true, + }, + "extends": [ + "airbnb-base", + ], + "parserOptions": { + "ecmaVersion": 12, + }, + "ignorePatterns": "*.externs.js", + "rules": { + "func-names": "off", + // Use tabs for consistency with the C++ codebase. + "indent": ["error", "tab"], + "max-len": "off", + "no-else-return": ["error", {allowElseIf: true}], + "curly": ["error", "all"], + "brace-style": ["error", "1tbs", { "allowSingleLine": false }], + "no-bitwise": "off", + "no-continue": "off", + "no-self-assign": "off", + "no-tabs": "off", + "no-param-reassign": ["error", { "props": false }], + "no-plusplus": "off", + "no-unused-vars": ["error", { "args": "none" }], + "prefer-destructuring": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "camelcase": "off", + "no-underscore-dangle": "off", + "max-classes-per-file": "off", + "prefer-arrow-callback": "off", + // Messes up with copyright headers in source files. + "spaced-comment": "off", + // Completely breaks emscripten libraries. + "object-shorthand": "off", + // Closure compiler (exported properties) + "quote-props": ["error", "consistent"], + "dot-notation": "off", + } +}; diff --git a/platform/javascript/.eslintrc.libs.js b/platform/javascript/.eslintrc.libs.js new file mode 100644 index 00000000000..e5f0c3d147f --- /dev/null +++ b/platform/javascript/.eslintrc.libs.js @@ -0,0 +1,22 @@ +module.exports = { + "extends": [ + "./.eslintrc.js", + ], + "globals": { + "LibraryManager": true, + "mergeInto": true, + "autoAddDeps": true, + "HEAP8": true, + "HEAPU8": true, + "HEAP32": true, + "HEAPF32": true, + "ERRNO_CODES": true, + "FS": true, + "IDBFS": true, + "GodotOS": true, + "GodotConfig": true, + "GodotRuntime": true, + "GodotFS": true, + "IDHandler": true, + }, +}; diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json new file mode 100644 index 00000000000..8e298a495ec --- /dev/null +++ b/platform/javascript/package-lock.json @@ -0,0 +1,1605 @@ +{ + "name": "godot", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", + "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz", + "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.1.3", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-config-airbnb-base": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", + "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.9", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", + "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-callable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", + "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } + } +} diff --git a/platform/javascript/package.json b/platform/javascript/package.json new file mode 100644 index 00000000000..630b584f5b2 --- /dev/null +++ b/platform/javascript/package.json @@ -0,0 +1,24 @@ +{ + "name": "godot", + "private": true, + "version": "1.0.0", + "description": "Linting setup for Godot's HTML5 platform code", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "npm run lint:engine && npm run lint:libs && npm run lint:modules", + "lint:engine": "eslint \"js/engine/*.js\" --no-eslintrc -c .eslintrc.engine.js", + "lint:libs": "eslint \"js/libs/*.js\" --no-eslintrc -c .eslintrc.libs.js", + "lint:modules": "eslint \"../../modules/**/*.js\" --no-eslintrc -c .eslintrc.libs.js", + "format": "npm run format:engine && npm run format:libs && npm run format:modules", + "format:engine": "npm run lint:engine -- --fix", + "format:libs": "npm run lint:libs -- --fix", + "format:modules": "npm run lint:modules -- --fix" + }, + "author": "Godot Engine contributors", + "license": "MIT", + "devDependencies": { + "eslint": "^7.9.0", + "eslint-config-airbnb-base": "^14.2.0", + "eslint-plugin-import": "^2.22.0" + } +} From f316a1719d3f451893a85667e6b76740a78e88e2 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 23 Nov 2020 13:27:13 +0100 Subject: [PATCH 3/3] [HTML5] Run eslint --fix. Should I write a poem about this whole new world? ;) --- modules/webrtc/library_godot_webrtc.js | 184 +++++++++--------- modules/websocket/library_godot_websocket.js | 62 +++--- platform/javascript/js/engine/engine.js | 145 +++++++------- platform/javascript/js/engine/preloader.js | 66 +++---- platform/javascript/js/engine/utils.js | 33 ++-- platform/javascript/js/libs/audio.worklet.js | 8 +- .../javascript/js/libs/library_godot_audio.js | 116 +++++------ .../js/libs/library_godot_display.js | 169 ++++++++-------- .../js/libs/library_godot_editor_tools.js | 2 +- .../javascript/js/libs/library_godot_eval.js | 56 +++--- .../js/libs/library_godot_http_request.js | 68 +++---- .../javascript/js/libs/library_godot_os.js | 89 +++++---- .../js/libs/library_godot_runtime.js | 30 +-- 13 files changed, 518 insertions(+), 510 deletions(-) diff --git a/modules/webrtc/library_godot_webrtc.js b/modules/webrtc/library_godot_webrtc.js index c8a10018e58..3b2a8fe60c8 100644 --- a/modules/webrtc/library_godot_webrtc.js +++ b/modules/webrtc/library_godot_webrtc.js @@ -32,7 +32,7 @@ const GodotRTCDataChannel = { // Our socket implementation that forwards events to C++. $GodotRTCDataChannel__deps: ['$IDHandler', '$GodotRuntime'], $GodotRTCDataChannel: { - connect: function(p_id, p_on_open, p_on_message, p_on_error, p_on_close) { + connect: function (p_id, p_on_open, p_on_message, p_on_error, p_on_close) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -48,31 +48,31 @@ const GodotRTCDataChannel = { ref.onerror = function (event) { p_on_error(); }; - ref.onmessage = function(event) { - var buffer; - var is_string = 0; + ref.onmessage = function (event) { + let buffer; + let is_string = 0; if (event.data instanceof ArrayBuffer) { buffer = new Uint8Array(event.data); } else if (event.data instanceof Blob) { - GodotRuntime.error("Blob type not supported"); + GodotRuntime.error('Blob type not supported'); return; - } else if (typeof event.data === "string") { + } else if (typeof event.data === 'string') { is_string = 1; - var enc = new TextEncoder("utf-8"); + const enc = new TextEncoder('utf-8'); buffer = new Uint8Array(enc.encode(event.data)); } else { - GodotRuntime.error("Unknown message type"); + GodotRuntime.error('Unknown message type'); return; } - var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = GodotRuntime.malloc(len); + const len = buffer.length * buffer.BYTES_PER_ELEMENT; + const out = GodotRuntime.malloc(len); HEAPU8.set(buffer, out); p_on_message(out, len, is_string); GodotRuntime.free(out); - } + }; }, - close: function(p_id) { + close: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -84,39 +84,39 @@ const GodotRTCDataChannel = { ref.close(); }, - get_prop: function(p_id, p_prop, p_def) { + get_prop: function (p_id, p_prop, p_def) { const ref = IDHandler.get(p_id); return (ref && ref[p_prop] !== undefined) ? ref[p_prop] : p_def; }, }, - godot_js_rtc_datachannel_ready_state_get: function(p_id) { + godot_js_rtc_datachannel_ready_state_get: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return 3; // CLOSED } - switch(ref.readyState) { - case "connecting": - return 0; - case "open": - return 1; - case "closing": - return 2; - case "closed": - default: - return 3; + switch (ref.readyState) { + case 'connecting': + return 0; + case 'open': + return 1; + case 'closing': + return 2; + case 'closed': + default: + return 3; } }, - godot_js_rtc_datachannel_send: function(p_id, p_buffer, p_length, p_raw) { + godot_js_rtc_datachannel_send: function (p_id, p_buffer, p_length, p_raw) { const ref = IDHandler.get(p_id); if (!ref) { return 1; } const bytes_array = new Uint8Array(p_length); - for (var i = 0; i < p_length; i++) { + for (let i = 0; i < p_length; i++) { bytes_array[i] = GodotRuntime.getHeapValue(p_buffer + i, 'i8'); } @@ -129,15 +129,15 @@ const GodotRTCDataChannel = { return 0; }, - godot_js_rtc_datachannel_is_ordered: function(p_id) { + godot_js_rtc_datachannel_is_ordered: function (p_id) { return IDHandler.get_prop(p_id, 'ordered', true); }, - godot_js_rtc_datachannel_id_get: function(p_id) { + godot_js_rtc_datachannel_id_get: function (p_id) { return IDHandler.get_prop(p_id, 'id', 65535); }, - godot_js_rtc_datachannel_max_packet_lifetime_get: function(p_id) { + godot_js_rtc_datachannel_max_packet_lifetime_get: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return 65535; @@ -151,15 +151,15 @@ const GodotRTCDataChannel = { return 65535; }, - godot_js_rtc_datachannel_max_retransmits_get: function(p_id) { + godot_js_rtc_datachannel_max_retransmits_get: function (p_id) { return IDHandler.get_prop(p_id, 'maxRetransmits', 65535); }, - godot_js_rtc_datachannel_is_negotiated: function(p_id, p_def) { + godot_js_rtc_datachannel_is_negotiated: function (p_id, p_def) { return IDHandler.get_prop(p_id, 'negotiated', 65535); }, - godot_js_rtc_datachannel_label_get: function(p_id) { + godot_js_rtc_datachannel_label_get: function (p_id) { const ref = IDHandler.get(p_id); if (!ref || !ref.label) { return 0; @@ -167,7 +167,7 @@ const GodotRTCDataChannel = { return GodotRuntime.allocString(ref.label); }, - godot_js_rtc_datachannel_protocol_get: function(p_id) { + godot_js_rtc_datachannel_protocol_get: function (p_id) { const ref = IDHandler.get(p_id); if (!ref || !ref.protocol) { return 0; @@ -175,12 +175,12 @@ const GodotRTCDataChannel = { return GodotRuntime.allocString(ref.protocol); }, - godot_js_rtc_datachannel_destroy: function(p_id) { + godot_js_rtc_datachannel_destroy: function (p_id) { GodotRTCDataChannel.close(p_id); IDHandler.remove(p_id); }, - godot_js_rtc_datachannel_connect: function(p_id, p_ref, p_on_open, p_on_message, p_on_error, p_on_close) { + godot_js_rtc_datachannel_connect: function (p_id, p_ref, p_on_open, p_on_message, p_on_error, p_on_close) { const onopen = GodotRuntime.get_func(p_on_open).bind(null, p_ref); const onmessage = GodotRuntime.get_func(p_on_message).bind(null, p_ref); const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_ref); @@ -188,7 +188,7 @@ const GodotRTCDataChannel = { GodotRTCDataChannel.connect(p_id, onopen, onmessage, onerror, onclose); }, - godot_js_rtc_datachannel_close: function(p_id) { + godot_js_rtc_datachannel_close: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -203,52 +203,52 @@ mergeInto(LibraryManager.library, GodotRTCDataChannel); const GodotRTCPeerConnection = { $GodotRTCPeerConnection__deps: ['$IDHandler', '$GodotRuntime', '$GodotRTCDataChannel'], $GodotRTCPeerConnection: { - onstatechange: function(p_id, p_conn, callback, event) { + onstatechange: function (p_id, p_conn, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; } - var state = 5; // CLOSED - switch(p_conn.iceConnectionState) { - case "new": - state = 0; - break; - case "checking": - state = 1; - break; - case "connected": - case "completed": - state = 2; - break; - case "disconnected": - state = 3; - break; - case "failed": - state = 4; - break; - case "closed": - default: - state = 5; - break; + let state = 5; // CLOSED + switch (p_conn.iceConnectionState) { + case 'new': + state = 0; + break; + case 'checking': + state = 1; + break; + case 'connected': + case 'completed': + state = 2; + break; + case 'disconnected': + state = 3; + break; + case 'failed': + state = 4; + break; + case 'closed': + default: + state = 5; + break; } callback(state); }, - onicecandidate: function(p_id, callback, event) { + onicecandidate: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref || !event.candidate) { return; } - let c = event.candidate; - let candidate_str = GodotRuntime.allocString(c.candidate); - let mid_str = GodotRuntime.allocString(c.sdpMid); + const c = event.candidate; + const candidate_str = GodotRuntime.allocString(c.candidate); + const mid_str = GodotRuntime.allocString(c.sdpMid); callback(mid_str, c.sdpMLineIndex, candidate_str); GodotRuntime.free(candidate_str); GodotRuntime.free(mid_str); }, - ondatachannel: function(p_id, callback, event) { + ondatachannel: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -258,19 +258,19 @@ const GodotRTCPeerConnection = { callback(cid); }, - onsession: function(p_id, callback, session) { + onsession: function (p_id, callback, session) { const ref = IDHandler.get(p_id); if (!ref) { return; } - let type_str = GodotRuntime.allocString(session.type); - let sdp_str = GodotRuntime.allocString(session.sdp); + const type_str = GodotRuntime.allocString(session.type); + const sdp_str = GodotRuntime.allocString(session.sdp); callback(type_str, sdp_str); GodotRuntime.free(type_str); GodotRuntime.free(sdp_str); }, - onerror: function(p_id, callback, error) { + onerror: function (p_id, callback, error) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -280,13 +280,13 @@ const GodotRTCPeerConnection = { }, }, - godot_js_rtc_pc_create: function(p_config, p_ref, p_on_state_change, p_on_candidate, p_on_datachannel) { + godot_js_rtc_pc_create: function (p_config, p_ref, p_on_state_change, p_on_candidate, p_on_datachannel) { const onstatechange = GodotRuntime.get_func(p_on_state_change).bind(null, p_ref); const oncandidate = GodotRuntime.get_func(p_on_candidate).bind(null, p_ref); const ondatachannel = GodotRuntime.get_func(p_on_datachannel).bind(null, p_ref); - var config = JSON.parse(GodotRuntime.parseString(p_config)); - var conn = null; + const config = JSON.parse(GodotRuntime.parseString(p_config)); + let conn = null; try { conn = new RTCPeerConnection(config); } catch (e) { @@ -302,7 +302,7 @@ const GodotRTCPeerConnection = { return id; }, - godot_js_rtc_pc_close: function(p_id) { + godot_js_rtc_pc_close: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -310,7 +310,7 @@ const GodotRTCPeerConnection = { ref.close(); }, - godot_js_rtc_pc_destroy: function(p_id) { + godot_js_rtc_pc_destroy: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -321,21 +321,21 @@ const GodotRTCPeerConnection = { IDHandler.remove(p_id); }, - godot_js_rtc_pc_offer_create: function(p_id, p_obj, p_on_session, p_on_error) { + godot_js_rtc_pc_offer_create: function (p_id, p_obj, p_on_session, p_on_error) { const ref = IDHandler.get(p_id); if (!ref) { return; } const onsession = GodotRuntime.get_func(p_on_session).bind(null, p_obj); const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_obj); - ref.createOffer().then(function(session) { + ref.createOffer().then(function (session) { GodotRTCPeerConnection.onsession(p_id, onsession, session); - }).catch(function(error) { + }).catch(function (error) { GodotRTCPeerConnection.onerror(p_id, onerror, error); }); }, - godot_js_rtc_pc_local_description_set: function(p_id, p_type, p_sdp, p_obj, p_on_error) { + godot_js_rtc_pc_local_description_set: function (p_id, p_type, p_sdp, p_obj, p_on_error) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -345,13 +345,13 @@ const GodotRTCPeerConnection = { const onerror = GodotRuntime.get_func(p_on_error).bind(null, p_obj); ref.setLocalDescription({ 'sdp': sdp, - 'type': type - }).catch(function(error) { + 'type': type, + }).catch(function (error) { GodotRTCPeerConnection.onerror(p_id, onerror, error); }); }, - godot_js_rtc_pc_remote_description_set: function(p_id, p_type, p_sdp, p_obj, p_session_created, p_on_error) { + godot_js_rtc_pc_remote_description_set: function (p_id, p_type, p_sdp, p_obj, p_session_created, p_on_error) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -362,35 +362,35 @@ const GodotRTCPeerConnection = { const onsession = GodotRuntime.get_func(p_session_created).bind(null, p_obj); ref.setRemoteDescription({ 'sdp': sdp, - 'type': type - }).then(function() { + 'type': type, + }).then(function () { if (type !== 'offer') { return Promise.resolve(); } - return ref.createAnswer().then(function(session) { + return ref.createAnswer().then(function (session) { GodotRTCPeerConnection.onsession(p_id, onsession, session); }); - }).catch(function(error) { + }).catch(function (error) { GodotRTCPeerConnection.onerror(p_id, onerror, error); }); }, - godot_js_rtc_pc_ice_candidate_add: function(p_id, p_mid_name, p_mline_idx, p_sdp) { + godot_js_rtc_pc_ice_candidate_add: function (p_id, p_mid_name, p_mline_idx, p_sdp) { const ref = IDHandler.get(p_id); if (!ref) { return; } - var sdpMidName = GodotRuntime.parseString(p_mid_name); - var sdpName = GodotRuntime.parseString(p_sdp); + const sdpMidName = GodotRuntime.parseString(p_mid_name); + const sdpName = GodotRuntime.parseString(p_sdp); ref.addIceCandidate(new RTCIceCandidate({ - "candidate": sdpName, - "sdpMid": sdpMidName, - "sdpMlineIndex": p_mline_idx, + 'candidate': sdpName, + 'sdpMid': sdpMidName, + 'sdpMlineIndex': p_mline_idx, })); }, godot_js_rtc_pc_datachannel_create__deps: ['$GodotRTCDataChannel'], - godot_js_rtc_pc_datachannel_create: function(p_id, p_label, p_config) { + godot_js_rtc_pc_datachannel_create: function (p_id, p_label, p_config) { try { const ref = IDHandler.get(p_id); if (!ref) { @@ -409,5 +409,5 @@ const GodotRTCPeerConnection = { }, }; -autoAddDeps(GodotRTCPeerConnection, '$GodotRTCPeerConnection') +autoAddDeps(GodotRTCPeerConnection, '$GodotRTCPeerConnection'); mergeInto(LibraryManager.library, GodotRTCPeerConnection); diff --git a/modules/websocket/library_godot_websocket.js b/modules/websocket/library_godot_websocket.js index 0856cb13e62..6ada4e73357 100644 --- a/modules/websocket/library_godot_websocket.js +++ b/modules/websocket/library_godot_websocket.js @@ -33,46 +33,46 @@ const GodotWebSocket = { $GodotWebSocket__deps: ['$IDHandler', '$GodotRuntime'], $GodotWebSocket: { // Connection opened, report selected protocol - _onopen: function(p_id, callback, event) { + _onopen: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; // Godot object is gone. } - let c_str = GodotRuntime.allocString(ref.protocol); + const c_str = GodotRuntime.allocString(ref.protocol); callback(c_str); GodotRuntime.free(c_str); }, // Message received, report content and type (UTF8 vs binary) - _onmessage: function(p_id, callback, event) { + _onmessage: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; // Godot object is gone. } - var buffer; - var is_string = 0; + let buffer; + let is_string = 0; if (event.data instanceof ArrayBuffer) { buffer = new Uint8Array(event.data); } else if (event.data instanceof Blob) { - GodotRuntime.error("Blob type not supported"); + GodotRuntime.error('Blob type not supported'); return; - } else if (typeof event.data === "string") { + } else if (typeof event.data === 'string') { is_string = 1; - var enc = new TextEncoder("utf-8"); + const enc = new TextEncoder('utf-8'); buffer = new Uint8Array(enc.encode(event.data)); } else { - GodotRuntime.error("Unknown message type"); + GodotRuntime.error('Unknown message type'); return; } - var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = GodotRuntime.malloc(len); + const len = buffer.length * buffer.BYTES_PER_ELEMENT; + const out = GodotRuntime.malloc(len); HEAPU8.set(buffer, out); callback(out, len, is_string); GodotRuntime.free(out); }, // An error happened, 'onclose' will be called after this. - _onerror: function(p_id, callback, event) { + _onerror: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; // Godot object is gone. @@ -81,18 +81,18 @@ const GodotWebSocket = { }, // Connection is closed, this is always fired. Report close code, reason, and clean status. - _onclose: function(p_id, callback, event) { + _onclose: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; // Godot object is gone. } - let c_str = GodotRuntime.allocString(event.reason); + const c_str = GodotRuntime.allocString(event.reason); callback(event.code, c_str, event.wasClean ? 1 : 0); GodotRuntime.free(c_str); }, // Send a message - send: function(p_id, p_data) { + send: function (p_id, p_data) { const ref = IDHandler.get(p_id); if (!ref || ref.readyState !== ref.OPEN) { return 1; // Godot object is gone or socket is not in a ready state. @@ -101,7 +101,7 @@ const GodotWebSocket = { return 0; }, - create: function(socket, p_on_open, p_on_message, p_on_error, p_on_close) { + create: function (socket, p_on_open, p_on_message, p_on_error, p_on_close) { const id = IDHandler.add(socket); socket.onopen = GodotWebSocket._onopen.bind(null, id, p_on_open); socket.onmessage = GodotWebSocket._onmessage.bind(null, id, p_on_message); @@ -111,7 +111,7 @@ const GodotWebSocket = { }, // Closes the JavaScript WebSocket (if not already closing) associated to a given C++ object. - close: function(p_id, p_code, p_reason) { + close: function (p_id, p_code, p_reason) { const ref = IDHandler.get(p_id); if (ref && ref.readyState < ref.CLOSING) { const code = p_code; @@ -121,7 +121,7 @@ const GodotWebSocket = { }, // Deletes the reference to a C++ object (closing any connected socket if necessary). - destroy: function(p_id) { + destroy: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -135,50 +135,50 @@ const GodotWebSocket = { }, }, - godot_js_websocket_create: function(p_ref, p_url, p_proto, p_on_open, p_on_message, p_on_error, p_on_close) { + godot_js_websocket_create: function (p_ref, p_url, p_proto, p_on_open, p_on_message, p_on_error, p_on_close) { const on_open = GodotRuntime.get_func(p_on_open).bind(null, p_ref); const on_message = GodotRuntime.get_func(p_on_message).bind(null, p_ref); const on_error = GodotRuntime.get_func(p_on_error).bind(null, p_ref); const on_close = GodotRuntime.get_func(p_on_close).bind(null, p_ref); const url = GodotRuntime.parseString(p_url); const protos = GodotRuntime.parseString(p_proto); - var socket = null; + let socket = null; try { if (protos) { - socket = new WebSocket(url, protos.split(",")); + socket = new WebSocket(url, protos.split(',')); } else { socket = new WebSocket(url); } } catch (e) { return 0; } - socket.binaryType = "arraybuffer"; + socket.binaryType = 'arraybuffer'; return GodotWebSocket.create(socket, on_open, on_message, on_error, on_close); }, - godot_js_websocket_send: function(p_id, p_buf, p_buf_len, p_raw) { - var bytes_array = new Uint8Array(p_buf_len); - var i = 0; - for(i = 0; i < p_buf_len; i++) { + godot_js_websocket_send: function (p_id, p_buf, p_buf_len, p_raw) { + const bytes_array = new Uint8Array(p_buf_len); + let i = 0; + for (i = 0; i < p_buf_len; i++) { bytes_array[i] = GodotRuntime.getHeapValue(p_buf + i, 'i8'); } - var out = bytes_array.buffer; + let out = bytes_array.buffer; if (!p_raw) { - out = new TextDecoder("utf-8").decode(bytes_array); + out = new TextDecoder('utf-8').decode(bytes_array); } return GodotWebSocket.send(p_id, out); }, - godot_js_websocket_close: function(p_id, p_code, p_reason) { + godot_js_websocket_close: function (p_id, p_code, p_reason) { const code = p_code; const reason = GodotRuntime.parseString(p_reason); GodotWebSocket.close(p_id, code, reason); }, - godot_js_websocket_destroy: function(p_id) { + godot_js_websocket_destroy: function (p_id) { GodotWebSocket.destroy(p_id); }, }; -autoAddDeps(GodotWebSocket, '$GodotWebSocket') +autoAddDeps(GodotWebSocket, '$GodotWebSocket'); mergeInto(LibraryManager.library, GodotWebSocket); diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js index e0d20946fc0..74153b672ac 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 8641646e6e1..ec34fb93f2a 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() { + const animateProgress = function () { + let loaded = 0; + let total = 0; + let totalIsValid = true; + let progressIsFinal = true; - var loaded = 0; - var total = 0; - var totalIsValid = true; - var 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 fbab9ba9f90..d0fca4e1cbf 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; - } + }, }; diff --git a/platform/javascript/js/libs/audio.worklet.js b/platform/javascript/js/libs/audio.worklet.js index a27035ef224..414dc370975 100644 --- a/platform/javascript/js/libs/audio.worklet.js +++ b/platform/javascript/js/libs/audio.worklet.js @@ -105,7 +105,7 @@ class GodotProcessor extends AudioWorkletProcessor { } parse_message(p_cmd, p_data) { - if (p_cmd === "start" && p_data) { + if (p_cmd === 'start' && p_data) { const state = p_data[0]; let idx = 0; this.lock = state.subarray(idx, ++idx); @@ -114,7 +114,7 @@ class GodotProcessor extends AudioWorkletProcessor { const avail_out = state.subarray(idx, ++idx); this.input = new RingBuffer(p_data[1], avail_in); this.output = new RingBuffer(p_data[2], avail_out); - } else if (p_cmd === "stop") { + } else if (p_cmd === 'stop') { this.runing = false; this.output = null; this.input = null; @@ -143,7 +143,7 @@ class GodotProcessor extends AudioWorkletProcessor { GodotProcessor.write_input(this.input_buffer, input); this.input.write(this.input_buffer); } else { - this.port.postMessage("Input buffer is full! Skipping input frame."); + this.port.postMessage('Input buffer is full! Skipping input frame.'); } } const process_output = GodotProcessor.array_has_data(outputs); @@ -157,7 +157,7 @@ class GodotProcessor extends AudioWorkletProcessor { this.output.read(this.output_buffer); GodotProcessor.write_output(output, this.output_buffer); } else { - this.port.postMessage("Output buffer has not enough frames! Skipping output frame."); + this.port.postMessage('Output buffer has not enough frames! Skipping output frame.'); } } this.process_notify(); diff --git a/platform/javascript/js/libs/library_godot_audio.js b/platform/javascript/js/libs/library_godot_audio.js index a657d0a1259..0c1f477f340 100644 --- a/platform/javascript/js/libs/library_godot_audio.js +++ b/platform/javascript/js/libs/library_godot_audio.js @@ -36,32 +36,32 @@ const GodotAudio = { driver: null, interval: 0, - init: function(mix_rate, latency, onstatechange, onlatencyupdate) { + init: function (mix_rate, latency, onstatechange, onlatencyupdate) { const ctx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: mix_rate, // latencyHint: latency / 1000 // Do not specify, leave 'interactive' for good performance. }); GodotAudio.ctx = ctx; - ctx.onstatechange = function() { + ctx.onstatechange = function () { let state = 0; switch (ctx.state) { - case 'suspended': - state = 0; - break; - case 'running': - state = 1; - break; - case 'closed': - state = 2; - break; + case 'suspended': + state = 0; + break; + case 'running': + state = 1; + break; + case 'closed': + state = 2; + break; // no default } onstatechange(state); - } + }; ctx.onstatechange(); // Immeditately notify state. // Update computed latency - GodotAudio.interval = setInterval(function() { + GodotAudio.interval = setInterval(function () { let computed_latency = 0; if (ctx.baseLatency) { computed_latency += GodotAudio.ctx.baseLatency; @@ -75,29 +75,33 @@ const GodotAudio = { return ctx.destination.channelCount; }, - create_input: function(callback) { + create_input: function (callback) { if (GodotAudio.input) { return; // Already started. } function gotMediaInput(stream) { GodotAudio.input = GodotAudio.ctx.createMediaStreamSource(stream); - callback(GodotAudio.input) + callback(GodotAudio.input); } if (navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ - "audio": true - }).then(gotMediaInput, function(e) { GodotRuntime.print(e) }); + 'audio': true, + }).then(gotMediaInput, function (e) { + GodotRuntime.print(e); + }); } else { if (!navigator.getUserMedia) { navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; } navigator.getUserMedia({ - "audio": true - }, gotMediaInput, function(e) { GodotRuntime.print(e) }); + 'audio': true, + }, gotMediaInput, function (e) { + GodotRuntime.print(e); + }); } }, - close_async: function(resolve, reject) { + close_async: function (resolve, reject) { const ctx = GodotAudio.ctx; GodotAudio.ctx = null; // Audio was not initialized. @@ -120,14 +124,14 @@ const GodotAudio = { if (GodotAudio.driver) { closed = GodotAudio.driver.close(); } - closed.then(function() { + closed.then(function () { return ctx.close(); - }).then(function() { + }).then(function () { ctx.onstatechange = null; resolve(); - }).catch(function(e) { + }).catch(function (e) { ctx.onstatechange = null; - GodotRuntime.error("Error closing AudioContext", e); + GodotRuntime.error('Error closing AudioContext', e); resolve(); }); }, @@ -141,30 +145,30 @@ const GodotAudio = { return 1; }, - godot_audio_init: function(p_mix_rate, p_latency, p_state_change, p_latency_update) { + godot_audio_init: function (p_mix_rate, p_latency, p_state_change, p_latency_update) { const statechange = GodotRuntime.get_func(p_state_change); const latencyupdate = GodotRuntime.get_func(p_latency_update); return GodotAudio.init(p_mix_rate, p_latency, statechange, latencyupdate); }, - godot_audio_resume: function() { + godot_audio_resume: function () { if (GodotAudio.ctx && GodotAudio.ctx.state !== 'running') { GodotAudio.ctx.resume(); } }, godot_audio_capture_start__proxy: 'sync', - godot_audio_capture_start: function() { + godot_audio_capture_start: function () { if (GodotAudio.input) { return; // Already started. } - GodotAudio.create_input(function(input) { + GodotAudio.create_input(function (input) { input.connect(GodotAudio.driver.get_node()); }); }, godot_audio_capture_stop__proxy: 'sync', - godot_audio_capture_stop: function() { + godot_audio_capture_stop: function () { if (GodotAudio.input) { const tracks = GodotAudio.input['mediaStream']['getTracks'](); for (let i = 0; i < tracks.length; i++) { @@ -176,7 +180,7 @@ const GodotAudio = { }, }; -autoAddDeps(GodotAudio, "$GodotAudio"); +autoAddDeps(GodotAudio, '$GodotAudio'); mergeInto(LibraryManager.library, GodotAudio); /** @@ -188,42 +192,42 @@ const GodotAudioWorklet = { promise: null, worklet: null, - create: function(channels) { + create: function (channels) { const path = GodotConfig.locate_file('godot.audio.worklet.js'); - GodotAudioWorklet.promise = GodotAudio.ctx.audioWorklet.addModule(path).then(function() { + GodotAudioWorklet.promise = GodotAudio.ctx.audioWorklet.addModule(path).then(function () { GodotAudioWorklet.worklet = new AudioWorkletNode( GodotAudio.ctx, 'godot-processor', { - 'outputChannelCount': [channels] - } + 'outputChannelCount': [channels], + }, ); return Promise.resolve(); }); GodotAudio.driver = GodotAudioWorklet; }, - start: function(in_buf, out_buf, state) { - GodotAudioWorklet.promise.then(function() { + start: function (in_buf, out_buf, state) { + GodotAudioWorklet.promise.then(function () { const node = GodotAudioWorklet.worklet; node.connect(GodotAudio.ctx.destination); node.port.postMessage({ 'cmd': 'start', 'data': [state, in_buf, out_buf], }); - node.port.onmessage = function(event) { + node.port.onmessage = function (event) { GodotRuntime.error(event.data); }; }); }, - get_node: function() { + get_node: function () { return GodotAudioWorklet.worklet; }, - close: function() { - return new Promise(function(resolve, reject) { - GodotAudioWorklet.promise.then(function() { + close: function () { + return new Promise(function (resolve, reject) { + GodotAudioWorklet.promise.then(function () { GodotAudioWorklet.worklet.port.postMessage({ 'cmd': 'stop', 'data': null, @@ -237,32 +241,32 @@ const GodotAudioWorklet = { }, }, - godot_audio_worklet_create: function(channels) { + godot_audio_worklet_create: function (channels) { GodotAudioWorklet.create(channels); }, - godot_audio_worklet_start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, p_state) { + godot_audio_worklet_start: function (p_in_buf, p_in_size, p_out_buf, p_out_size, p_state) { const out_buffer = GodotRuntime.heapSub(HEAPF32, p_out_buf, p_out_size); const in_buffer = GodotRuntime.heapSub(HEAPF32, p_in_buf, p_in_size); const state = GodotRuntime.heapSub(HEAP32, p_state, 4); GodotAudioWorklet.start(in_buffer, out_buffer, state); }, - godot_audio_worklet_state_wait: function(p_state, p_idx, p_expected, p_timeout) { + godot_audio_worklet_state_wait: function (p_state, p_idx, p_expected, p_timeout) { Atomics.wait(HEAP32, (p_state >> 2) + p_idx, p_expected, p_timeout); return Atomics.load(HEAP32, (p_state >> 2) + p_idx); }, - godot_audio_worklet_state_add: function(p_state, p_idx, p_value) { + godot_audio_worklet_state_add: function (p_state, p_idx, p_value) { return Atomics.add(HEAP32, (p_state >> 2) + p_idx, p_value); }, - godot_audio_worklet_state_get: function(p_state, p_idx) { + godot_audio_worklet_state_get: function (p_state, p_idx) { return Atomics.load(HEAP32, (p_state >> 2) + p_idx); }, }; -autoAddDeps(GodotAudioWorklet, "$GodotAudioWorklet"); +autoAddDeps(GodotAudioWorklet, '$GodotAudioWorklet'); mergeInto(LibraryManager.library, GodotAudioWorklet); /* @@ -273,14 +277,14 @@ const GodotAudioScript = { $GodotAudioScript: { script: null, - create: function(buffer_length, channel_count) { + create: function (buffer_length, channel_count) { GodotAudioScript.script = GodotAudio.ctx.createScriptProcessor(buffer_length, 2, channel_count); GodotAudio.driver = GodotAudioScript; return GodotAudioScript.script.bufferSize; }, - start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, onprocess) { - GodotAudioScript.script.onaudioprocess = function(event) { + start: function (p_in_buf, p_in_size, p_out_buf, p_out_size, onprocess) { + GodotAudioScript.script.onaudioprocess = function (event) { // Read input const inb = GodotRuntime.heapSub(HEAPF32, p_in_buf, p_in_size); const input = event.inputBuffer; @@ -312,12 +316,12 @@ const GodotAudioScript = { GodotAudioScript.script.connect(GodotAudio.ctx.destination); }, - get_node: function() { + get_node: function () { return GodotAudioScript.script; }, - close: function() { - return new Promise(function(resolve, reject) { + close: function () { + return new Promise(function (resolve, reject) { GodotAudioScript.script.disconnect(); GodotAudioScript.script.onaudioprocess = null; GodotAudioScript.script = null; @@ -326,15 +330,15 @@ const GodotAudioScript = { }, }, - godot_audio_script_create: function(buffer_length, channel_count) { + godot_audio_script_create: function (buffer_length, channel_count) { return GodotAudioScript.create(buffer_length, channel_count); }, - godot_audio_script_start: function(p_in_buf, p_in_size, p_out_buf, p_out_size, p_cb) { + godot_audio_script_start: function (p_in_buf, p_in_size, p_out_buf, p_out_size, p_cb) { const onprocess = GodotRuntime.get_func(p_cb); GodotAudioScript.start(p_in_buf, p_in_size, p_out_buf, p_out_size, onprocess); }, }; -autoAddDeps(GodotAudioScript, "$GodotAudioScript"); +autoAddDeps(GodotAudioScript, '$GodotAudioScript'); mergeInto(LibraryManager.library, GodotAudioScript); diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 28f63ba5576..9651b48952d 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -38,13 +38,13 @@ const GodotDisplayListeners = { $GodotDisplayListeners: { handlers: [], - has: function(target, event, method, capture) { - return GodotDisplayListeners.handlers.findIndex(function(e) { + has: function (target, event, method, capture) { + return GodotDisplayListeners.handlers.findIndex(function (e) { return e.target === target && e.event === event && e.method === method && e.capture === capture; }) !== -1; }, - add: function(target, event, method, capture) { + add: function (target, event, method, capture) { if (GodotDisplayListeners.has(target, event, method, capture)) { return; } @@ -53,13 +53,13 @@ const GodotDisplayListeners = { this.event = p_event; this.method = p_method; this.capture = p_capture; - }; + } GodotDisplayListeners.handlers.push(new Handler(target, event, method, capture)); target.addEventListener(event, method, capture); }, - clear: function() { - GodotDisplayListeners.handlers.forEach(function(h) { + clear: function () { + GodotDisplayListeners.handlers.forEach(function (h) { h.target.removeEventListener(h.event, h.method, h.capture); }); GodotDisplayListeners.handlers.length = 0; @@ -84,20 +84,20 @@ const GodotDisplayDragDrop = { promises: [], pending_files: [], - add_entry: function(entry) { + add_entry: function (entry) { if (entry.isDirectory) { GodotDisplayDragDrop.add_dir(entry); } else if (entry.isFile) { GodotDisplayDragDrop.add_file(entry); } else { - GodotRuntime.error("Unrecognized entry...", entry); + GodotRuntime.error('Unrecognized entry...', entry); } }, - add_dir: function(entry) { - GodotDisplayDragDrop.promises.push(new Promise(function(resolve, reject) { + add_dir: function (entry) { + GodotDisplayDragDrop.promises.push(new Promise(function (resolve, reject) { const reader = entry.createReader(); - reader.readEntries(function(entries) { + reader.readEntries(function (entries) { for (let i = 0; i < entries.length; i++) { GodotDisplayDragDrop.add_entry(entries[i]); } @@ -106,58 +106,58 @@ const GodotDisplayDragDrop = { })); }, - add_file: function(entry) { - GodotDisplayDragDrop.promises.push(new Promise(function(resolve, reject) { - entry.file(function(file) { + add_file: function (entry) { + GodotDisplayDragDrop.promises.push(new Promise(function (resolve, reject) { + entry.file(function (file) { const reader = new FileReader(); - reader.onload = function() { + reader.onload = function () { const f = { - "path": file.relativePath || file.webkitRelativePath, - "name": file.name, - "type": file.type, - "size": file.size, - "data": reader.result + 'path': file.relativePath || file.webkitRelativePath, + 'name': file.name, + 'type': file.type, + 'size': file.size, + 'data': reader.result, }; if (!f['path']) { f['path'] = f['name']; } GodotDisplayDragDrop.pending_files.push(f); - resolve() + resolve(); }; - reader.onerror = function() { - GodotRuntime.print("Error reading file"); + reader.onerror = function () { + GodotRuntime.print('Error reading file'); reject(); - } + }; reader.readAsArrayBuffer(file); - }, function(err) { - GodotRuntime.print("Error!"); + }, function (err) { + GodotRuntime.print('Error!'); reject(); }); })); }, - process: function(resolve, reject) { + process: function (resolve, reject) { if (GodotDisplayDragDrop.promises.length === 0) { resolve(); return; } - GodotDisplayDragDrop.promises.pop().then(function() { - setTimeout(function() { + GodotDisplayDragDrop.promises.pop().then(function () { + setTimeout(function () { GodotDisplayDragDrop.process(resolve, reject); }, 0); }); }, - _process_event: function(ev, callback) { + _process_event: function (ev, callback) { ev.preventDefault(); if (ev.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) for (let i = 0; i < ev.dataTransfer.items.length; i++) { const item = ev.dataTransfer.items[i]; let entry = null; - if ("getAsEntry" in item) { + if ('getAsEntry' in item) { entry = item.getAsEntry(); - } else if ("webkitGetAsEntry" in item) { + } else if ('webkitGetAsEntry' in item) { entry = item.webkitGetAsEntry(); } if (entry) { @@ -165,24 +165,24 @@ const GodotDisplayDragDrop = { } } } else { - GodotRuntime.error("File upload not supported"); + GodotRuntime.error('File upload not supported'); } - new Promise(GodotDisplayDragDrop.process).then(function() { - const DROP = "/tmp/drop-" + parseInt(Math.random() * (1 << 30), 10) + "/"; + new Promise(GodotDisplayDragDrop.process).then(function () { + const DROP = `/tmp/drop-${parseInt(Math.random() * (1 << 30), 10)}/`; const drops = []; const files = []; FS.mkdir(DROP); GodotDisplayDragDrop.pending_files.forEach((elem) => { const path = elem['path']; GodotFS.copy_to_fs(DROP + path, elem['data']); - let idx = path.indexOf("/"); + let idx = path.indexOf('/'); if (idx === -1) { // Root file drops.push(DROP + path); } else { // Subdir const sub = path.substr(0, idx); - idx = sub.indexOf("/"); + idx = sub.indexOf('/'); if (idx < 0 && drops.indexOf(DROP + sub) === -1) { drops.push(DROP + sub); } @@ -192,37 +192,38 @@ const GodotDisplayDragDrop = { GodotDisplayDragDrop.promises = []; GodotDisplayDragDrop.pending_files = []; callback(drops); - const dirs = [DROP.substr(0, DROP.length -1)]; + const dirs = [DROP.substr(0, DROP.length - 1)]; // Remove temporary files files.forEach(function (file) { FS.unlink(file); - let dir = file.replace(DROP, ""); - let idx = dir.lastIndexOf("/"); + let dir = file.replace(DROP, ''); + let idx = dir.lastIndexOf('/'); while (idx > 0) { dir = dir.substr(0, idx); if (dirs.indexOf(DROP + dir) === -1) { dirs.push(DROP + dir); } - idx = dir.lastIndexOf("/"); + idx = dir.lastIndexOf('/'); } }); // Remove dirs. - dirs.sort(function(a, b) { + dirs.sort(function (a, b) { const al = (a.match(/\//g) || []).length; const bl = (b.match(/\//g) || []).length; - if (al > bl) + if (al > bl) { return -1; - else if (al < bl) + } else if (al < bl) { return 1; + } return 0; - }).forEach(function(dir) { + }).forEach(function (dir) { FS.rmdir(dir); }); }); }, - handler: function(callback) { - return function(ev) { + handler: function (callback) { + return function (ev) { GodotDisplayDragDrop._process_event(ev, callback); }; }, @@ -241,25 +242,25 @@ const GodotDisplayCursor = { shape: 'auto', visible: true, cursors: {}, - set_style: function(style) { + set_style: function (style) { GodotConfig.canvas.style.cursor = style; }, - set_shape: function(shape) { + set_shape: function (shape) { GodotDisplayCursor.shape = shape; let css = shape; if (shape in GodotDisplayCursor.cursors) { const c = GodotDisplayCursor.cursors[shape]; - css = 'url("' + c.url + '") ' + c.x + ' ' + c.y + ', auto'; + css = `url("${c.url}") ${c.x} ${c.y}, auto`; } if (GodotDisplayCursor.visible) { GodotDisplayCursor.set_style(css); } }, - clear: function() { + clear: function () { GodotDisplayCursor.set_style(''); GodotDisplayCursor.shape = 'auto'; GodotDisplayCursor.visible = true; - Object.keys(GodotDisplayCursor.cursors).forEach(function(key) { + Object.keys(GodotDisplayCursor.cursors).forEach(function (key) { URL.revokeObjectURL(GodotDisplayCursor.cursors[key]); delete GodotDisplayCursor.cursors[key]; }); @@ -279,35 +280,35 @@ const GodotDisplay = { window_icon: '', }, - godot_js_display_is_swap_ok_cancel: function() { + godot_js_display_is_swap_ok_cancel: function () { const win = (['Windows', 'Win64', 'Win32', 'WinCE']); - const plat = navigator.platform || ""; + const plat = navigator.platform || ''; if (win.indexOf(plat) !== -1) { return 1; } return 0; }, - godot_js_display_alert: function(p_text) { + godot_js_display_alert: function (p_text) { window.alert(GodotRuntime.parseString(p_text)); // eslint-disable-line no-alert }, - godot_js_display_pixel_ratio_get: function() { + godot_js_display_pixel_ratio_get: function () { return window.devicePixelRatio || 1; }, /* * Canvas */ - godot_js_display_canvas_focus: function() { + godot_js_display_canvas_focus: function () { GodotConfig.canvas.focus(); }, - godot_js_display_canvas_is_focused: function() { + godot_js_display_canvas_is_focused: function () { return document.activeElement === GodotConfig.canvas; }, - godot_js_display_canvas_bounding_rect_position_get: function(r_x, r_y) { + godot_js_display_canvas_bounding_rect_position_get: function (r_x, r_y) { const brect = GodotConfig.canvas.getBoundingClientRect(); GodotRuntime.setHeapValue(r_x, brect.x, 'i32'); GodotRuntime.setHeapValue(r_y, brect.y, 'i32'); @@ -316,26 +317,26 @@ const GodotDisplay = { /* * Touchscreen */ - godot_js_display_touchscreen_is_available: function() { + godot_js_display_touchscreen_is_available: function () { return 'ontouchstart' in window; }, /* * Clipboard */ - godot_js_display_clipboard_set: function(p_text) { + godot_js_display_clipboard_set: function (p_text) { const text = GodotRuntime.parseString(p_text); if (!navigator.clipboard || !navigator.clipboard.writeText) { return 1; } - navigator.clipboard.writeText(text).catch(function(e) { + navigator.clipboard.writeText(text).catch(function (e) { // Setting OS clipboard is only possible from an input callback. - GodotRuntime.error("Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:", e); + GodotRuntime.error('Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:', e); }); return 0; }, - godot_js_display_clipboard_get: function(callback) { + godot_js_display_clipboard_get: function (callback) { const func = GodotRuntime.get_func(callback); try { navigator.clipboard.readText().then(function (result) { @@ -353,19 +354,19 @@ const GodotDisplay = { /* * Window */ - godot_js_display_window_request_fullscreen: function() { + godot_js_display_window_request_fullscreen: function () { const canvas = GodotConfig.canvas; - (canvas.requestFullscreen || canvas.msRequestFullscreen || - canvas.mozRequestFullScreen || canvas.mozRequestFullscreen || - canvas.webkitRequestFullscreen + (canvas.requestFullscreen || canvas.msRequestFullscreen + || canvas.mozRequestFullScreen || canvas.mozRequestFullscreen + || canvas.webkitRequestFullscreen ).call(canvas); }, - godot_js_display_window_title_set: function(p_data) { + godot_js_display_window_title_set: function (p_data) { document.title = GodotRuntime.parseString(p_data); }, - godot_js_display_window_icon_set: function(p_ptr, p_len) { + godot_js_display_window_icon_set: function (p_ptr, p_len) { let link = document.getElementById('-gd-engine-icon'); if (link === null) { link = document.createElement('link'); @@ -374,7 +375,7 @@ const GodotDisplay = { document.head.appendChild(link); } const old_icon = GodotDisplay.window_icon; - const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: "image/png" }); + const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: 'image/png' }); GodotDisplay.window_icon = URL.createObjectURL(png); link.href = GodotDisplay.window_icon; if (old_icon) { @@ -385,7 +386,7 @@ const GodotDisplay = { /* * Cursor */ - godot_js_display_cursor_set_visible: function(p_visible) { + godot_js_display_cursor_set_visible: function (p_visible) { const visible = p_visible !== 0; if (visible === GodotDisplayCursor.visible) { return; @@ -398,15 +399,15 @@ const GodotDisplay = { } }, - godot_js_display_cursor_is_hidden: function() { + godot_js_display_cursor_is_hidden: function () { return !GodotDisplayCursor.visible; }, - godot_js_display_cursor_set_shape: function(p_string) { + godot_js_display_cursor_set_shape: function (p_string) { GodotDisplayCursor.set_shape(GodotRuntime.parseString(p_string)); }, - godot_js_display_cursor_set_custom_shape: function(p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) { + godot_js_display_cursor_set_custom_shape: function (p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) { const shape = GodotRuntime.parseString(p_shape); const old_shape = GodotDisplayCursor.cursors[shape]; if (p_len > 0) { @@ -431,20 +432,20 @@ const GodotDisplay = { /* * Listeners */ - godot_js_display_notification_cb: function(callback, p_enter, p_exit, p_in, p_out) { + godot_js_display_notification_cb: function (callback, p_enter, p_exit, p_in, p_out) { const canvas = GodotConfig.canvas; const func = GodotRuntime.get_func(callback); const notif = [p_enter, p_exit, p_in, p_out]; - ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function(evt_name, idx) { - GodotDisplayListeners.add(canvas, evt_name, function() { + ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function (evt_name, idx) { + GodotDisplayListeners.add(canvas, evt_name, function () { func.bind(null, notif[idx]); }, true); }); }, - godot_js_display_paste_cb: function(callback) { + godot_js_display_paste_cb: function (callback) { const func = GodotRuntime.get_func(callback); - GodotDisplayListeners.add(window, 'paste', function(evt) { + GodotDisplayListeners.add(window, 'paste', function (evt) { const text = evt.clipboardData.getData('text'); const ptr = GodotRuntime.allocString(text); func(ptr); @@ -452,9 +453,9 @@ const GodotDisplay = { }, false); }, - godot_js_display_drop_files_cb: function(callback) { - const func = GodotRuntime.get_func(callback) - const dropFiles = function(files) { + godot_js_display_drop_files_cb: function (callback) { + const func = GodotRuntime.get_func(callback); + const dropFiles = function (files) { const args = files || []; if (!args.length) { return; @@ -465,7 +466,7 @@ const GodotDisplay = { GodotRuntime.freeStringArray(argv, argc); }; const canvas = GodotConfig.canvas; - GodotDisplayListeners.add(canvas, 'dragover', function(ev) { + GodotDisplayListeners.add(canvas, 'dragover', function (ev) { // Prevent default behavior (which would try to open the file(s)) ev.preventDefault(); }, false); diff --git a/platform/javascript/js/libs/library_godot_editor_tools.js b/platform/javascript/js/libs/library_godot_editor_tools.js index 21e40185aea..f39fed04a83 100644 --- a/platform/javascript/js/libs/library_godot_editor_tools.js +++ b/platform/javascript/js/libs/library_godot_editor_tools.js @@ -30,7 +30,7 @@ const GodotEditorTools = { godot_js_editor_download_file__deps: ['$FS'], - godot_js_editor_download_file: function(p_path, p_name, p_mime) { + godot_js_editor_download_file: function (p_path, p_name, p_mime) { const path = GodotRuntime.parseString(p_path); const name = GodotRuntime.parseString(p_name); const mime = GodotRuntime.parseString(p_mime); diff --git a/platform/javascript/js/libs/library_godot_eval.js b/platform/javascript/js/libs/library_godot_eval.js index 4064938d3e9..33ff2317267 100644 --- a/platform/javascript/js/libs/library_godot_eval.js +++ b/platform/javascript/js/libs/library_godot_eval.js @@ -30,7 +30,7 @@ const GodotEval = { godot_js_eval__deps: ['$GodotRuntime'], - godot_js_eval: function(p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) { + godot_js_eval: function (p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) { const js_code = GodotRuntime.parseString(p_js); let eval_ret = null; try { @@ -46,42 +46,40 @@ const GodotEval = { } switch (typeof eval_ret) { + case 'boolean': + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); + return 1; // BOOL - case 'boolean': - GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); - return 1; // BOOL + case 'number': + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double'); + return 3; // REAL - case 'number': - GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double'); - return 3; // REAL + case 'string': + GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*'); + return 4; // STRING - case 'string': - GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*'); - return 4; // STRING - - case 'object': - if (eval_ret === null) { - break; - } - - if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) { - eval_ret = new Uint8Array(eval_ret.buffer); - } - else if (eval_ret instanceof ArrayBuffer) { - eval_ret = new Uint8Array(eval_ret); - } - if (eval_ret instanceof Uint8Array) { - const func = GodotRuntime.get_func(p_callback); - const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length); - HEAPU8.set(eval_ret, bytes_ptr); - return 20; // POOL_BYTE_ARRAY - } + case 'object': + if (eval_ret === null) { break; + } + + if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) { + eval_ret = new Uint8Array(eval_ret.buffer); + } else if (eval_ret instanceof ArrayBuffer) { + eval_ret = new Uint8Array(eval_ret); + } + if (eval_ret instanceof Uint8Array) { + const func = GodotRuntime.get_func(p_callback); + const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length); + HEAPU8.set(eval_ret, bytes_ptr); + return 20; // POOL_BYTE_ARRAY + } + break; // no default } return 0; // NIL }, -} +}; mergeInto(LibraryManager.library, GodotEval); diff --git a/platform/javascript/js/libs/library_godot_http_request.js b/platform/javascript/js/libs/library_godot_http_request.js index 6f80f3b9580..2b9aa88208f 100644 --- a/platform/javascript/js/libs/library_godot_http_request.js +++ b/platform/javascript/js/libs/library_godot_http_request.js @@ -33,111 +33,113 @@ const GodotHTTPRequest = { $GodotHTTPRequest: { requests: [], - getUnusedRequestId: function() { - var idMax = GodotHTTPRequest.requests.length; - for (var potentialId = 0; potentialId < idMax; ++potentialId) { + getUnusedRequestId: function () { + const idMax = GodotHTTPRequest.requests.length; + for (let potentialId = 0; potentialId < idMax; ++potentialId) { if (GodotHTTPRequest.requests[potentialId] instanceof XMLHttpRequest) { continue; } return potentialId; } - GodotHTTPRequest.requests.push(null) + GodotHTTPRequest.requests.push(null); return idMax; }, - setupRequest: function(xhr) { + setupRequest: function (xhr) { xhr.responseType = 'arraybuffer'; }, }, - godot_xhr_new: function() { - var newId = GodotHTTPRequest.getUnusedRequestId(); - GodotHTTPRequest.requests[newId] = new XMLHttpRequest; + godot_xhr_new: function () { + const newId = GodotHTTPRequest.getUnusedRequestId(); + GodotHTTPRequest.requests[newId] = new XMLHttpRequest(); GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[newId]); return newId; }, - godot_xhr_reset: function(xhrId) { - GodotHTTPRequest.requests[xhrId] = new XMLHttpRequest; + godot_xhr_reset: function (xhrId) { + GodotHTTPRequest.requests[xhrId] = new XMLHttpRequest(); GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[xhrId]); }, - godot_xhr_free: function(xhrId) { + godot_xhr_free: function (xhrId) { GodotHTTPRequest.requests[xhrId].abort(); GodotHTTPRequest.requests[xhrId] = null; }, - godot_xhr_open: function(xhrId, method, url, p_user, p_password) { + godot_xhr_open: function (xhrId, method, url, p_user, p_password) { const user = p_user > 0 ? GodotRuntime.parseString(p_user) : null; const password = p_password > 0 ? GodotRuntime.parseString(p_password) : null; GodotHTTPRequest.requests[xhrId].open(GodotRuntime.parseString(method), GodotRuntime.parseString(url), true, user, password); }, - godot_xhr_set_request_header: function(xhrId, header, value) { + godot_xhr_set_request_header: function (xhrId, header, value) { GodotHTTPRequest.requests[xhrId].setRequestHeader(GodotRuntime.parseString(header), GodotRuntime.parseString(value)); }, - godot_xhr_send_null: function(xhrId) { + godot_xhr_send_null: function (xhrId) { GodotHTTPRequest.requests[xhrId].send(); }, - godot_xhr_send_string: function(xhrId, strPtr) { + godot_xhr_send_string: function (xhrId, strPtr) { if (!strPtr) { - GodotRuntime.error("Failed to send string per XHR: null pointer"); + GodotRuntime.error('Failed to send string per XHR: null pointer'); return; } GodotHTTPRequest.requests[xhrId].send(GodotRuntime.parseString(strPtr)); }, - godot_xhr_send_data: function(xhrId, ptr, len) { + godot_xhr_send_data: function (xhrId, ptr, len) { if (!ptr) { - GodotRuntime.error("Failed to send data per XHR: null pointer"); + GodotRuntime.error('Failed to send data per XHR: null pointer'); return; } if (len < 0) { - GodotRuntime.error("Failed to send data per XHR: buffer length less than 0"); + GodotRuntime.error('Failed to send data per XHR: buffer length less than 0'); return; } GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len)); }, - godot_xhr_abort: function(xhrId) { + godot_xhr_abort: function (xhrId) { GodotHTTPRequest.requests[xhrId].abort(); }, - godot_xhr_get_status: function(xhrId) { + godot_xhr_get_status: function (xhrId) { return GodotHTTPRequest.requests[xhrId].status; }, - godot_xhr_get_ready_state: function(xhrId) { + godot_xhr_get_ready_state: function (xhrId) { return GodotHTTPRequest.requests[xhrId].readyState; }, - godot_xhr_get_response_headers_length: function(xhrId) { - var headers = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); + godot_xhr_get_response_headers_length: function (xhrId) { + const headers = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); return headers === null ? 0 : GodotRuntime.strlen(headers); }, - godot_xhr_get_response_headers: function(xhrId, dst, len) { - var str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); - if (str === null) + godot_xhr_get_response_headers: function (xhrId, dst, len) { + const str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders(); + if (str === null) { return; + } GodotRuntime.stringToHeap(str, dst, len); }, - godot_xhr_get_response_length: function(xhrId) { - var body = GodotHTTPRequest.requests[xhrId].response; + godot_xhr_get_response_length: function (xhrId) { + const body = GodotHTTPRequest.requests[xhrId].response; return body === null ? 0 : body.byteLength; }, - godot_xhr_get_response: function(xhrId, dst, len) { - var buf = GodotHTTPRequest.requests[xhrId].response; - if (buf === null) + godot_xhr_get_response: function (xhrId, dst, len) { + let buf = GodotHTTPRequest.requests[xhrId].response; + if (buf === null) { return; + } buf = new Uint8Array(buf).subarray(0, len); HEAPU8.set(buf, dst); }, }; -autoAddDeps(GodotHTTPRequest, "$GodotHTTPRequest"); +autoAddDeps(GodotHTTPRequest, '$GodotHTTPRequest'); mergeInto(LibraryManager.library, GodotHTTPRequest); diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js index 582f04cb1b2..488753d7042 100644 --- a/platform/javascript/js/libs/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -33,23 +33,23 @@ const IDHandler = { _last_id: 0, _references: {}, - get: function(p_id) { + get: function (p_id) { return IDHandler._references[p_id]; }, - add: function(p_data) { + add: function (p_data) { const id = ++IDHandler._last_id; IDHandler._references[id] = p_data; return id; }, - remove: function(p_id) { + remove: function (p_id) { delete IDHandler._references[p_id]; }, }, }; -autoAddDeps(IDHandler, "$IDHandler"); +autoAddDeps(IDHandler, '$IDHandler'); mergeInto(LibraryManager.library, IDHandler); const GodotConfig = { @@ -57,12 +57,12 @@ const GodotConfig = { $GodotConfig__deps: ['$GodotRuntime'], $GodotConfig: { canvas: null, - locale: "en", + locale: 'en', resize_on_start: false, on_execute: null, - init_config: function(p_opts) { - GodotConfig.resize_on_start = p_opts['resizeCanvasOnStart'] ? true : false; + init_config: function (p_opts) { + GodotConfig.resize_on_start = !!p_opts['resizeCanvasOnStart']; GodotConfig.canvas = p_opts['canvas']; GodotConfig.locale = p_opts['locale'] || GodotConfig.locale; GodotConfig.on_execute = p_opts['onExecute']; @@ -70,20 +70,20 @@ const GodotConfig = { Module['onExit'] = p_opts['onExit']; // eslint-disable-line no-undef }, - locate_file: function(file) { - return Module["locateFile"](file); // eslint-disable-line no-undef + locate_file: function (file) { + return Module['locateFile'](file); // eslint-disable-line no-undef }, }, - godot_js_config_canvas_id_get: function(p_ptr, p_ptr_max) { - GodotRuntime.stringToHeap('#' + GodotConfig.canvas.id, p_ptr, p_ptr_max); + godot_js_config_canvas_id_get: function (p_ptr, p_ptr_max) { + GodotRuntime.stringToHeap(`#${GodotConfig.canvas.id}`, p_ptr, p_ptr_max); }, - godot_js_config_locale_get: function(p_ptr, p_ptr_max) { + godot_js_config_locale_get: function (p_ptr, p_ptr_max) { GodotRuntime.stringToHeap(GodotConfig.locale, p_ptr, p_ptr_max); }, - godot_js_config_is_resize_on_start: function() { + godot_js_config_is_resize_on_start: function () { return GodotConfig.resize_on_start ? 1 : 0; }, }; @@ -91,7 +91,6 @@ const GodotConfig = { autoAddDeps(GodotConfig, '$GodotConfig'); mergeInto(LibraryManager.library, GodotConfig); - const GodotFS = { $GodotFS__deps: ['$FS', '$IDBFS', '$GodotRuntime'], $GodotFS__postset: [ @@ -104,7 +103,7 @@ const GodotFS = { _syncing: false, _mount_points: [], - is_persistent: function() { + is_persistent: function () { return GodotFS._idbfs ? 1 : 0; }, @@ -112,7 +111,7 @@ const GodotFS = { // Returns a promise that resolves when the FS is ready. // We keep track of mount_points, so that we can properly close the IDBFS // since emscripten is not doing it by itself. (emscripten GH#12516). - init: function(persistentPaths) { + init: function (persistentPaths) { GodotFS._idbfs = false; if (!Array.isArray(persistentPaths)) { return Promise.reject(new Error('Persistent paths must be an array')); @@ -133,16 +132,16 @@ const GodotFS = { } } - GodotFS._mount_points.forEach(function(path) { + GodotFS._mount_points.forEach(function (path) { createRecursive(path); FS.mount(IDBFS, {}, path); }); - return new Promise(function(resolve, reject) { - FS.syncfs(true, function(err) { + return new Promise(function (resolve, reject) { + FS.syncfs(true, function (err) { if (err) { GodotFS._mount_points = []; GodotFS._idbfs = false; - GodotRuntime.print("IndexedDB not available: " + err.message); + GodotRuntime.print(`IndexedDB not available: ${err.message}`); } else { GodotFS._idbfs = true; } @@ -152,12 +151,12 @@ const GodotFS = { }, // Deinit godot file system, making sure to unmount file systems, and close IDBFS(s). - deinit: function() { - GodotFS._mount_points.forEach(function(path) { + deinit: function () { + GodotFS._mount_points.forEach(function (path) { try { FS.unmount(path); } catch (e) { - GodotRuntime.print("Already unmounted", e); + GodotRuntime.print('Already unmounted', e); } if (GodotFS._idbfs && IDBFS.dbs[path]) { IDBFS.dbs[path].close(); @@ -169,16 +168,16 @@ const GodotFS = { GodotFS._syncing = false; }, - sync: function() { + sync: function () { if (GodotFS._syncing) { GodotRuntime.error('Already syncing!'); return Promise.resolve(); } GodotFS._syncing = true; return new Promise(function (resolve, reject) { - FS.syncfs(false, function(error) { + FS.syncfs(false, function (error) { if (error) { - GodotRuntime.error('Failed to save IDB file system: ' + error.message); + GodotRuntime.error(`Failed to save IDB file system: ${error.message}`); } GodotFS._syncing = false; resolve(error); @@ -187,9 +186,9 @@ const GodotFS = { }, // Copies a buffer to the internal file system. Creating directories recursively. - copy_to_fs: function(path, buffer) { - const idx = path.lastIndexOf("/"); - let dir = "/"; + copy_to_fs: function (path, buffer) { + const idx = path.lastIndexOf('/'); + let dir = '/'; if (idx > 0) { dir = path.slice(0, idx); } @@ -201,7 +200,7 @@ const GodotFS = { } FS.mkdirTree(dir); } - FS.writeFile(path, new Uint8Array(buffer), {'flags': 'wx+'}); + FS.writeFile(path, new Uint8Array(buffer), { 'flags': 'wx+' }); }, }, }; @@ -214,54 +213,54 @@ const GodotOS = { 'GodotOS._fs_sync_promise = Promise.resolve();', ].join(''), $GodotOS: { - request_quit: function() {}, + request_quit: function () {}, _async_cbs: [], _fs_sync_promise: null, - atexit: function(p_promise_cb) { + atexit: function (p_promise_cb) { GodotOS._async_cbs.push(p_promise_cb); }, - finish_async: function(callback) { - GodotOS._fs_sync_promise.then(function(err) { + finish_async: function (callback) { + GodotOS._fs_sync_promise.then(function (err) { const promises = []; - GodotOS._async_cbs.forEach(function(cb) { + GodotOS._async_cbs.forEach(function (cb) { promises.push(new Promise(cb)); }); return Promise.all(promises); - }).then(function() { + }).then(function () { return GodotFS.sync(); // Final FS sync. - }).then(function(err) { + }).then(function (err) { // Always deferred. - setTimeout(function() { + setTimeout(function () { callback(); }, 0); }); }, }, - godot_js_os_finish_async: function(p_callback) { + godot_js_os_finish_async: function (p_callback) { const func = GodotRuntime.get_func(p_callback); GodotOS.finish_async(func); }, - godot_js_os_request_quit_cb: function(p_callback) { + godot_js_os_request_quit_cb: function (p_callback) { GodotOS.request_quit = GodotRuntime.get_func(p_callback); }, - godot_js_os_fs_is_persistent: function() { + godot_js_os_fs_is_persistent: function () { return GodotFS.is_persistent(); }, - godot_js_os_fs_sync: function(callback) { + godot_js_os_fs_sync: function (callback) { const func = GodotRuntime.get_func(callback); GodotOS._fs_sync_promise = GodotFS.sync(); - GodotOS._fs_sync_promise.then(function(err) { + GodotOS._fs_sync_promise.then(function (err) { func(); }); }, - godot_js_os_execute: function(p_json) { + godot_js_os_execute: function (p_json) { const json_args = GodotRuntime.parseString(p_json); const args = JSON.parse(json_args); if (GodotConfig.on_execute) { @@ -271,7 +270,7 @@ const GodotOS = { return 1; }, - godot_js_os_shell_open: function(p_uri) { + godot_js_os_shell_open: function (p_uri) { window.open(GodotRuntime.parseString(p_uri), '_blank'); }, }; diff --git a/platform/javascript/js/libs/library_godot_runtime.js b/platform/javascript/js/libs/library_godot_runtime.js index 1769f83623e..04f29ad6812 100644 --- a/platform/javascript/js/libs/library_godot_runtime.js +++ b/platform/javascript/js/libs/library_godot_runtime.js @@ -33,29 +33,29 @@ const GodotRuntime = { /* * Functions */ - get_func: function(ptr) { + get_func: function (ptr) { return wasmTable.get(ptr); // eslint-disable-line no-undef }, /* * Prints */ - error: function() { + error: function () { err.apply(null, Array.from(arguments)); // eslint-disable-line no-undef }, - print: function() { + print: function () { out.apply(null, Array.from(arguments)); // eslint-disable-line no-undef }, /* * Memory */ - malloc: function(p_size) { + malloc: function (p_size) { return _malloc(p_size); // eslint-disable-line no-undef }, - free: function(p_ptr) { + free: function (p_ptr) { _free(p_ptr); // eslint-disable-line no-undef }, @@ -63,16 +63,16 @@ const GodotRuntime = { return getValue(p_ptr, p_type); // eslint-disable-line no-undef }, - setHeapValue: function(p_ptr, p_value, p_type) { + setHeapValue: function (p_ptr, p_value, p_type) { setValue(p_ptr, p_value, p_type); // eslint-disable-line no-undef }, - heapSub: function(p_heap, p_ptr, p_len) { + heapSub: function (p_heap, p_ptr, p_len) { const bytes = p_heap.BYTES_PER_ELEMENT; return p_heap.subarray(p_ptr / bytes, p_ptr / bytes + p_len); }, - heapCopy: function(p_heap, p_ptr, p_len) { + heapCopy: function (p_heap, p_ptr, p_len) { const bytes = p_heap.BYTES_PER_ELEMENT; return p_heap.slice(p_ptr / bytes, p_ptr / bytes + p_len); }, @@ -80,22 +80,22 @@ const GodotRuntime = { /* * Strings */ - parseString: function(p_ptr) { + parseString: function (p_ptr) { return UTF8ToString(p_ptr); // eslint-disable-line no-undef }, - strlen: function(p_str) { + strlen: function (p_str) { return lengthBytesUTF8(p_str); // eslint-disable-line no-undef }, - allocString: function(p_str) { - const length = GodotRuntime.strlen(p_str)+1; + allocString: function (p_str) { + const length = GodotRuntime.strlen(p_str) + 1; const c_str = GodotRuntime.malloc(length); stringToUTF8(p_str, c_str, length); // eslint-disable-line no-undef return c_str; }, - allocStringArray: function(p_strings) { + allocStringArray: function (p_strings) { const size = p_strings.length; const c_ptr = GodotRuntime.malloc(size * 4); for (let i = 0; i < size; i++) { @@ -104,7 +104,7 @@ const GodotRuntime = { return c_ptr; }, - freeStringArray: function(p_ptr, p_len) { + freeStringArray: function (p_ptr, p_len) { for (let i = 0; i < p_len; i++) { GodotRuntime.free(HEAP32[(p_ptr >> 2) + i]); } @@ -116,5 +116,5 @@ const GodotRuntime = { }, }, }; -autoAddDeps(GodotRuntime, "$GodotRuntime"); +autoAddDeps(GodotRuntime, '$GodotRuntime'); mergeInto(LibraryManager.library, GodotRuntime);