diff options
22 files changed, 2603 insertions, 776 deletions
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index 3fa759bb03..da3327246b 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/modules/webrtc/library_godot_webrtc.js b/modules/webrtc/library_godot_webrtc.js index d4c38f15a2..3b2a8fe60c 100644 --- a/modules/webrtc/library_godot_webrtc.js +++ b/modules/webrtc/library_godot_webrtc.js @@ -28,11 +28,11 @@ /* 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) { + 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 @@ var 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) { - console.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 { - console.error("Unknown message type"); + GodotRuntime.error('Unknown message type'); return; } - var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = _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); - _free(out); - } + GodotRuntime.free(out); + }; }, - close: function(p_id) { + close: function (p_id) { const ref = IDHandler.get(p_id); if (!ref) { return; @@ -84,40 +84,40 @@ var 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": - return 3; + switch (ref.readyState) { + case 'connecting': + return 0; + case 'open': + return 1; + 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) { + 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++) { - bytes_array[i] = getValue(p_buffer + i, 'i8'); + for (let i = 0; i < p_length; i++) { + bytes_array[i] = GodotRuntime.getHeapValue(p_buffer + i, 'i8'); } if (p_raw) { @@ -126,17 +126,18 @@ 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) { + 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; @@ -150,44 +151,44 @@ var 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; } - return GodotOS.allocString(ref.label); + 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; } - return GodotOS.allocString(ref.protocol); + 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) { - 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); + 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); + const onclose = GodotRuntime.get_func(p_on_close).bind(null, p_ref); 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; @@ -199,48 +200,55 @@ 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) { + 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; - case "checking": - state = 1; - case "connected": - case "completed": - state = 2; - case "disconnected": - state = 3; - case "failed": - state = 4; - case "closed": - state = 5; + 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 = GodotOS.allocString(c.candidate); - let mid_str = GodotOS.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); - _free(candidate_str); - _free(mid_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; @@ -250,39 +258,39 @@ var 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 = GodotOS.allocString(session.type); - let sdp_str = GodotOS.allocString(session.sdp); + const type_str = GodotRuntime.allocString(session.type); + const 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) { + onerror: function (p_id, callback, error) { const ref = IDHandler.get(p_id); 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); + 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(UTF8ToString(p_config)); - var conn = null; + const config = JSON.parse(GodotRuntime.parseString(p_config)); + let conn = null; try { conn = new RTCPeerConnection(config); } catch (e) { - console.error(e); + GodotRuntime.error(e); return 0; } @@ -294,7 +302,7 @@ var 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; @@ -302,7 +310,7 @@ var 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; @@ -313,93 +321,93 @@ var 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 = GodotOS.get_func(p_on_session).bind(null, p_obj); - const onerror = GodotOS.get_func(p_on_error).bind(null, p_obj); - ref.createOffer().then(function(session) { + 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) { + }).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; } - 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 - }).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; } - 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; + '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 = UTF8ToString(p_mid_name); - var sdpName = UTF8ToString(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) { 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; } }, }; -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 7076a6f43d..6ada4e7335 100644 --- a/modules/websocket/library_godot_websocket.js +++ b/modules/websocket/library_godot_websocket.js @@ -28,51 +28,51 @@ /* 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) { + _onopen: function (p_id, callback, event) { const ref = IDHandler.get(p_id); if (!ref) { return; // Godot object is gone. } - let c_str = GodotOS.allocString(ref.protocol); + const 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) - _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) { - alert("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 { - alert("Unknown message type"); + GodotRuntime.error('Unknown message type'); return; } - var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = _malloc(len); + const len = buffer.length * buffer.BYTES_PER_ELEMENT; + const 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. - _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,27 +81,27 @@ var 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 = GodotOS.allocString(event.reason); + const 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) { + 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); 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,17 +111,17 @@ var 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; - const reason = UTF8ToString(p_reason); + const reason = GodotRuntime.parseString(p_reason); ref.close(code, reason); } }, // 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 @@ 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); - var socket = null; + 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); + 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++) { - bytes_array[i] = getValue(p_buf + i, 'i8'); + 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 = UTF8ToString(p_reason); + 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/.eslintrc.engine.js b/platform/javascript/.eslintrc.engine.js new file mode 100644 index 0000000000..00f0f147a9 --- /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 0000000000..0ff9d67d26 --- /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 0000000000..e5f0c3d147 --- /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/SCsub b/platform/javascript/SCsub index a0e6fa0e18..627ae778b1 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -20,27 +20,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) @@ -59,7 +60,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 b3467d009f..0000000000 --- a/platform/javascript/engine/preloader.js +++ /dev/null @@ -1,135 +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 index 1a94dd15ec..1a94dd15ec 100644 --- a/platform/javascript/engine/externs.js +++ b/platform/javascript/js/engine/engine.externs.js diff --git a/platform/javascript/engine/engine.js b/platform/javascript/js/engine/engine.js index 3745e04479..74153b672a 100644 --- a/platform/javascript/engine/engine.js +++ b/platform/javascript/js/engine/engine.js @@ -1,14 +1,14 @@ -Function('return this')()['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,14 +18,14 @@ Function('return this')()['Engine'] = (function() { requestAnimationFrame(preloader.animateProgress); } return loadPromise; - }; + } function unload() { loadPromise = null; - }; + } /** @constructor */ - function Engine() { + function Engine() { // eslint-disable-line no-shadow this.canvas = null; this.executableName = ''; this.rtenv = null; @@ -34,30 +34,32 @@ Function('return this')()['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,25 +73,28 @@ Function('return this')()['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')); } 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. @@ -98,18 +103,18 @@ Function('return this')()['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"); + 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]; @@ -122,14 +127,14 @@ Function('return this')()['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); @@ -138,8 +143,8 @@ Function('return this')()['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 @@ -150,95 +155,101 @@ Function('return this')()['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) { - text = Array.prototype.slice.call(arguments).join(" "); + msg = Array.prototype.slice.call(arguments).join(' '); } - func(text); + func(msg); }; - if (this.rtenv) + if (this.rtenv) { this.rtenv.print = print; + } stdout = print; }; - Engine.prototype.setStderrFunc = function(func) { - var printErr = function(text) { - if (arguments.length > 1) - text = Array.prototype.slice.call(arguments).join(" "); - func(text); + Engine.prototype.setStderrFunc = function (func) { + const printErr = function (text) { + let msg = text; + if (arguments.length > 1) { + 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'](); } @@ -268,4 +279,7 @@ Function('return this')()['Engine'] = (function() { Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths; Engine.prototype['requestQuit'] = Engine.prototype.requestQuit; return Engine; -})(); +}()); +if (typeof window !== 'undefined') { + window['Engine'] = Engine; +} diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js new file mode 100644 index 0000000000..ec34fb93f2 --- /dev/null +++ b/platform/javascript/js/engine/preloader.js @@ -0,0 +1,127 @@ +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 () { + 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 () { + let loaded = 0; + let total = 0; + let totalIsValid = true; + let 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') { + const 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(); + } + return Promise.reject(new Error('Invalid object for preloading')); + }; +}; diff --git a/platform/javascript/engine/utils.js b/platform/javascript/js/engine/utils.js index 8455739a25..d0fca4e1cb 100644 --- a/platform/javascript/engine/utils.js +++ b/platform/javascript/js/engine/utils.js @@ -1,51 +1,56 @@ -var Utils = { - createLocateRewrite: function(execName) { +const Utils = { // eslint-disable-line no-unused-vars + + 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) { - wasmLoader.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']); }); }); - wasmLoader = null; + 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]; } - throw new Error("No canvas found"); + 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) { 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 index f91787b993..414dc37097 100644 --- a/platform/javascript/native/audio.worklet.js +++ b/platform/javascript/js/libs/audio.worklet.js @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + class RingBuffer { constructor(p_buffer, p_state) { this.buffer = p_buffer; @@ -104,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); @@ -113,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; } @@ -131,39 +132,39 @@ 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."); + 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."); + this.port.postMessage('Output buffer has not enough frames! Skipping output frame.'); } } this.process_notify(); 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++) { @@ -172,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 index 3a0c8f297a..0c1f477f34 100644 --- a/platform/javascript/native/library_godot_audio.js +++ b/platform/javascript/js/libs/library_godot_audio.js @@ -29,73 +29,79 @@ /*************************************************************************/ const GodotAudio = { - $GodotAudio__deps: ['$GodotOS'], + $GodotAudio__deps: ['$GodotRuntime', '$GodotOS'], $GodotAudio: { ctx: null, input: null, 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; - onstatechange(ctx.state); // Immeditately notify state. - 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() { - let latency = 0; + GodotAudio.interval = setInterval(function () { + 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; }, - 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) { out(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) { out(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. @@ -118,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; - console.error("Error closing AudioContext", e); + GodotRuntime.error('Error closing AudioContext', e); resolve(); }); }, @@ -139,30 +145,30 @@ const GodotAudio = { return 1; }, - 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); + 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() { - if (GodotAudio.ctx && GodotAudio.ctx.state != 'running') { + 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++) { @@ -174,54 +180,54 @@ const GodotAudio = { }, }; -autoAddDeps(GodotAudio, "$GodotAudio"); +autoAddDeps(GodotAudio, '$GodotAudio'); 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'); - GodotAudioWorklet.promise = GodotAudio.ctx.audioWorklet.addModule(path).then(function() { + create: function (channels) { + const path = GodotConfig.locate_file('godot.audio.worklet.js'); + 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) { - console.error(event.data); + 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, @@ -235,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) { - 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); + 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); /* @@ -271,16 +277,16 @@ 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 = 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; @@ -296,7 +302,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++) { @@ -310,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; @@ -324,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) { - const onprocess = GodotOS.get_func(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/native/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 11bbfbc60d..9651b48952 100644 --- a/platform/javascript/native/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -33,32 +33,33 @@ * 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; + 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; } - 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); }, - 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; @@ -83,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 { - console.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]); } @@ -105,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() { - console.log("Error reading file"); + reader.onerror = function () { + GodotRuntime.print('Error reading file'); reject(); - } + }; reader.readAsArrayBuffer(file); - }, function(err) { - console.log("Error!"); + }, function (err) { + GodotRuntime.print('Error!'); reject(); }); })); }, - process: function(resolve, reject) { - if (GodotDisplayDragDrop.promises.length == 0) { + 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) { @@ -164,25 +165,25 @@ 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)) + "/"; + 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("/"); - if (idx == -1) { + let idx = path.indexOf('/'); + 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) { + idx = sub.indexOf('/'); + if (idx < 0 && drops.indexOf(DROP + sub) === -1) { drops.push(DROP + sub); } } @@ -191,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) { + 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); }; }, @@ -234,31 +236,31 @@ 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, 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]; }); @@ -273,75 +275,74 @@ 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: '', }, - 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) { - window.alert(UTF8ToString(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() { - return document.activeElement == GodotConfig.canvas; + 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(); - 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'); }, /* * 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) { - const text = UTF8ToString(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. - 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); + godot_js_display_clipboard_get: function (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. }); @@ -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) { - document.title = UTF8ToString(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([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) { @@ -385,9 +386,9 @@ const GodotDisplay = { /* * Cursor */ - godot_js_display_cursor_set_visible: function(p_visible) { - const visible = p_visible != 0; - if (visible == GodotDisplayCursor.visible) { + godot_js_display_cursor_set_visible: function (p_visible) { + const visible = p_visible !== 0; + if (visible === GodotDisplayCursor.visible) { return; } GodotDisplayCursor.visible = visible; @@ -398,19 +399,19 @@ 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) { - GodotDisplayCursor.set_shape(UTF8ToString(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) { - const shape = UTF8ToString(p_shape); + 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) { - 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, @@ -420,7 +421,7 @@ const GodotDisplay = { } else { delete GodotDisplayCursor.cursors[shape]; } - if (shape == GodotDisplayCursor.shape) { + if (shape === GodotDisplayCursor.shape) { GodotDisplayCursor.set_shape(GodotDisplayCursor.shape); } if (old_shape) { @@ -431,41 +432,41 @@ 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 = 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() { + ['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) { - const func = GodotOS.get_func(callback); - GodotDisplayListeners.add(window, 'paste', function(evt) { + godot_js_display_paste_cb: function (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 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; } 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) { + 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/native/library_godot_editor_tools.js b/platform/javascript/js/libs/library_godot_editor_tools.js index 202a198adb..f39fed04a8 100644 --- a/platform/javascript/native/library_godot_editor_tools.js +++ b/platform/javascript/js/libs/library_godot_editor_tools.js @@ -30,10 +30,10 @@ 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); + 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); 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 index 44d356a4fb..33ff231726 100644 --- a/platform/javascript/native/library_godot_eval.js +++ b/platform/javascript/js/libs/library_godot_eval.js @@ -29,57 +29,57 @@ /*************************************************************************/ const GodotEval = { - godot_js_eval__deps: ['$GodotOS'], - 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); + 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 = 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'); - return 1; // BOOL + case 'boolean': + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); + return 1; // BOOL - case 'number': - setValue(p_union_ptr, eval_ret, 'double'); - return 3; // REAL + case 'number': + 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 , '*'); - 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 = GodotOS.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/native/http_request.js b/platform/javascript/js/libs/library_godot_http_request.js index 272154aee3..2b9aa88208 100644 --- a/platform/javascript/native/http_request.js +++ b/platform/javascript/js/libs/library_godot_http_request.js @@ -27,118 +27,119 @@ /* 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() { - 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, 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)); + 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) { - 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) { + 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)); }, - 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(); - return headers === null ? 0 : lengthBytesUTF8(headers); + 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; - 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) { - 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/native/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js index a1424a691a..488753d704 100644 --- a/platform/javascript/native/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -33,52 +33,57 @@ 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 = { $GodotConfig__postset: 'Module["initConfig"] = GodotConfig.init_config;', + $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']; // 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); + 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) { - stringToUTF8(GodotConfig.locale, 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; }, }; @@ -87,7 +92,7 @@ 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;', @@ -98,7 +103,7 @@ const GodotFS = { _syncing: false, _mount_points: [], - is_persistent: function() { + is_persistent: function () { return GodotFS._idbfs ? 1 : 0; }, @@ -106,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')); @@ -127,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; - console.log("IndexedDB not available: " + err.message); + GodotRuntime.print(`IndexedDB not available: ${err.message}`); } else { GodotFS._idbfs = true; } @@ -146,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) { - console.log("Already unmounted", e); + GodotRuntime.print('Already unmounted', e); } if (GodotFS._idbfs && IDBFS.dbs[path]) { IDBFS.dbs[path].close(); @@ -163,16 +168,16 @@ const GodotFS = { GodotFS._syncing = false; }, - sync: function() { + 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) { + 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); @@ -181,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); } @@ -195,105 +200,68 @@ const GodotFS = { } FS.mkdirTree(dir); } - FS.writeFile(path, new Uint8Array(buffer), {'flags': 'wx+'}); + FS.writeFile(path, new Uint8Array(buffer), { 'flags': 'wx+' }); }, }, }; 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() {}, + request_quit: function () {}, _async_cbs: [], _fs_sync_promise: null, - get_func: function(ptr) { - return wasmTable.get(ptr); - }, - - 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); }); }, - - 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); + 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) { - GodotOS.request_quit = GodotOS.get_func(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) { - const func = GodotOS.get_func(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) { - const json_args = UTF8ToString(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) { GodotConfig.on_execute(args); @@ -302,8 +270,8 @@ const GodotOS = { return 1; }, - godot_js_os_shell_open: function(p_uri) { - window.open(UTF8ToString(p_uri), '_blank'); + 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 new file mode 100644 index 0000000000..04f29ad681 --- /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); diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json new file mode 100644 index 0000000000..8e298a495e --- /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 0000000000..630b584f5b --- /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" + } +} |