summaryrefslogtreecommitdiff
path: root/platform/web/js/libs/library_godot_fetch.js
diff options
context:
space:
mode:
Diffstat (limited to 'platform/web/js/libs/library_godot_fetch.js')
-rw-r--r--platform/web/js/libs/library_godot_fetch.js247
1 files changed, 247 insertions, 0 deletions
diff --git a/platform/web/js/libs/library_godot_fetch.js b/platform/web/js/libs/library_godot_fetch.js
new file mode 100644
index 0000000000..285e50a035
--- /dev/null
+++ b/platform/web/js/libs/library_godot_fetch.js
@@ -0,0 +1,247 @@
+/*************************************************************************/
+/* library_godot_fetch.js */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 GodotFetch = {
+ $GodotFetch__deps: ['$IDHandler', '$GodotRuntime'],
+ $GodotFetch: {
+
+ onread: function (id, result) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ if (result.value) {
+ obj.chunks.push(result.value);
+ }
+ obj.reading = false;
+ obj.done = result.done;
+ },
+
+ onresponse: function (id, response) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ let chunked = false;
+ response.headers.forEach(function (value, header) {
+ const v = value.toLowerCase().trim();
+ const h = header.toLowerCase().trim();
+ if (h === 'transfer-encoding' && v === 'chunked') {
+ chunked = true;
+ }
+ });
+ obj.status = response.status;
+ obj.response = response;
+ obj.reader = response.body.getReader();
+ obj.chunked = chunked;
+ },
+
+ onerror: function (id, err) {
+ GodotRuntime.error(err);
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ obj.error = err;
+ },
+
+ create: function (method, url, headers, body) {
+ const obj = {
+ request: null,
+ response: null,
+ reader: null,
+ error: null,
+ done: false,
+ reading: false,
+ status: 0,
+ chunks: [],
+ bodySize: -1,
+ };
+ const id = IDHandler.add(obj);
+ const init = {
+ method: method,
+ headers: headers,
+ body: body,
+ };
+ obj.request = fetch(url, init);
+ obj.request.then(GodotFetch.onresponse.bind(null, id)).catch(GodotFetch.onerror.bind(null, id));
+ return id;
+ },
+
+ free: function (id) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ IDHandler.remove(id);
+ if (!obj.request) {
+ return;
+ }
+ // Try to abort
+ obj.request.then(function (response) {
+ response.abort();
+ }).catch(function (e) { /* nothing to do */ });
+ },
+
+ read: function (id) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ if (obj.reader && !obj.reading) {
+ if (obj.done) {
+ obj.reader = null;
+ return;
+ }
+ obj.reading = true;
+ obj.reader.read().then(GodotFetch.onread.bind(null, id)).catch(GodotFetch.onerror.bind(null, id));
+ }
+ },
+ },
+
+ godot_js_fetch_create__sig: 'iiiiiii',
+ godot_js_fetch_create: function (p_method, p_url, p_headers, p_headers_size, p_body, p_body_size) {
+ const method = GodotRuntime.parseString(p_method);
+ const url = GodotRuntime.parseString(p_url);
+ const headers = GodotRuntime.parseStringArray(p_headers, p_headers_size);
+ const body = p_body_size ? GodotRuntime.heapSlice(HEAP8, p_body, p_body_size) : null;
+ return GodotFetch.create(method, url, headers.map(function (hv) {
+ const idx = hv.indexOf(':');
+ if (idx <= 0) {
+ return [];
+ }
+ return [
+ hv.slice(0, idx).trim(),
+ hv.slice(idx + 1).trim(),
+ ];
+ }).filter(function (v) {
+ return v.length === 2;
+ }), body);
+ },
+
+ godot_js_fetch_state_get__sig: 'ii',
+ godot_js_fetch_state_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj) {
+ return -1;
+ }
+ if (obj.error) {
+ return -1;
+ }
+ if (!obj.response) {
+ return 0;
+ }
+ if (obj.reader) {
+ return 1;
+ }
+ if (obj.done) {
+ return 2;
+ }
+ return -1;
+ },
+
+ godot_js_fetch_http_status_get__sig: 'ii',
+ godot_js_fetch_http_status_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 0;
+ }
+ return obj.status;
+ },
+
+ godot_js_fetch_read_headers__sig: 'iiii',
+ godot_js_fetch_read_headers: function (p_id, p_parse_cb, p_ref) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 1;
+ }
+ const cb = GodotRuntime.get_func(p_parse_cb);
+ const arr = [];
+ obj.response.headers.forEach(function (v, h) {
+ arr.push(`${h}:${v}`);
+ });
+ const c_ptr = GodotRuntime.allocStringArray(arr);
+ cb(arr.length, c_ptr, p_ref);
+ GodotRuntime.freeStringArray(c_ptr, arr.length);
+ return 0;
+ },
+
+ godot_js_fetch_read_chunk__sig: 'iiii',
+ godot_js_fetch_read_chunk: function (p_id, p_buf, p_buf_size) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 0;
+ }
+ let to_read = p_buf_size;
+ const chunks = obj.chunks;
+ while (to_read && chunks.length) {
+ const chunk = obj.chunks[0];
+ if (chunk.length > to_read) {
+ GodotRuntime.heapCopy(HEAP8, chunk.slice(0, to_read), p_buf);
+ chunks[0] = chunk.slice(to_read);
+ to_read = 0;
+ } else {
+ GodotRuntime.heapCopy(HEAP8, chunk, p_buf);
+ to_read -= chunk.length;
+ chunks.pop();
+ }
+ }
+ if (!chunks.length) {
+ GodotFetch.read(p_id);
+ }
+ return p_buf_size - to_read;
+ },
+
+ godot_js_fetch_body_length_get__sig: 'ii',
+ godot_js_fetch_body_length_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return -1;
+ }
+ return obj.bodySize;
+ },
+
+ godot_js_fetch_is_chunked__sig: 'ii',
+ godot_js_fetch_is_chunked: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return -1;
+ }
+ return obj.chunked ? 1 : 0;
+ },
+
+ godot_js_fetch_free__sig: 'vi',
+ godot_js_fetch_free: function (id) {
+ GodotFetch.free(id);
+ },
+};
+
+autoAddDeps(GodotFetch, '$GodotFetch');
+mergeInto(LibraryManager.library, GodotFetch);