summaryrefslogtreecommitdiff
path: root/platform/javascript/native
diff options
context:
space:
mode:
Diffstat (limited to 'platform/javascript/native')
-rw-r--r--platform/javascript/native/http_request.js146
-rw-r--r--platform/javascript/native/id_handler.js63
-rw-r--r--platform/javascript/native/utils.js204
3 files changed, 413 insertions, 0 deletions
diff --git a/platform/javascript/native/http_request.js b/platform/javascript/native/http_request.js
new file mode 100644
index 0000000000..f621689f9d
--- /dev/null
+++ b/platform/javascript/native/http_request.js
@@ -0,0 +1,146 @@
+/*************************************************************************/
+/* http_request.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. */
+/*************************************************************************/
+var GodotHTTPRequest = {
+
+ $GodotHTTPRequest: {
+
+ requests: [],
+
+ getUnusedRequestId: function() {
+ var idMax = GodotHTTPRequest.requests.length;
+ for (var potentialId = 0; potentialId < idMax; ++potentialId) {
+ if (GodotHTTPRequest.requests[potentialId] instanceof XMLHttpRequest) {
+ continue;
+ }
+ return potentialId;
+ }
+ GodotHTTPRequest.requests.push(null)
+ return idMax;
+ },
+
+ setupRequest: function(xhr) {
+ xhr.responseType = 'arraybuffer';
+ },
+ },
+
+ godot_xhr_new: function() {
+ var 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;
+ GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[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_set_request_header: function(xhrId, header, value) {
+ GodotHTTPRequest.requests[xhrId].setRequestHeader(UTF8ToString(header), UTF8ToString(value));
+ },
+
+ godot_xhr_send_null: function(xhrId) {
+ GodotHTTPRequest.requests[xhrId].send();
+ },
+
+ godot_xhr_send_string: function(xhrId, strPtr) {
+ if (!strPtr) {
+ err("Failed to send string per XHR: null pointer");
+ return;
+ }
+ GodotHTTPRequest.requests[xhrId].send(UTF8ToString(strPtr));
+ },
+
+ godot_xhr_send_data: function(xhrId, ptr, len) {
+ if (!ptr) {
+ err("Failed to send data per XHR: null pointer");
+ return;
+ }
+ if (len < 0) {
+ err("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) {
+ GodotHTTPRequest.requests[xhrId].abort();
+ },
+
+ godot_xhr_get_status: function(xhrId) {
+ return GodotHTTPRequest.requests[xhrId].status;
+ },
+
+ 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: function(xhrId, dst, len) {
+ var str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders();
+ if (str === null)
+ return;
+ var buf = new Uint8Array(len + 1);
+ stringToUTF8Array(str, buf, 0, buf.length);
+ buf = buf.subarray(0, -1);
+ HEAPU8.set(buf, dst);
+ },
+
+ godot_xhr_get_response_length: function(xhrId) {
+ var 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)
+ return;
+ buf = new Uint8Array(buf).subarray(0, len);
+ HEAPU8.set(buf, dst);
+ },
+};
+
+autoAddDeps(GodotHTTPRequest, "$GodotHTTPRequest");
+mergeInto(LibraryManager.library, GodotHTTPRequest);
diff --git a/platform/javascript/native/id_handler.js b/platform/javascript/native/id_handler.js
new file mode 100644
index 0000000000..67d29075b8
--- /dev/null
+++ b/platform/javascript/native/id_handler.js
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* id_handler.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. */
+/*************************************************************************/
+
+var IDHandler = /** @constructor */ function() {
+
+ var ids = {};
+ var size = 0;
+
+ this.has = function(id) {
+ return ids.hasOwnProperty(id);
+ }
+
+ this.add = function(obj) {
+ size += 1;
+ var id = crypto.getRandomValues(new Int32Array(32))[0];
+ ids[id] = obj;
+ return id;
+ }
+
+ this.get = function(id) {
+ return ids[id];
+ }
+
+ this.remove = function(id) {
+ size -= 1;
+ delete ids[id];
+ }
+
+ this.size = function() {
+ return size;
+ }
+
+ this.ids = ids;
+};
+
+Module.IDHandler = new IDHandler;
diff --git a/platform/javascript/native/utils.js b/platform/javascript/native/utils.js
new file mode 100644
index 0000000000..95585d26ae
--- /dev/null
+++ b/platform/javascript/native/utils.js
@@ -0,0 +1,204 @@
+/*************************************************************************/
+/* utils.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. */
+/*************************************************************************/
+
+Module['copyToFS'] = function(path, buffer) {
+ var p = path.lastIndexOf("/");
+ var dir = "/";
+ if (p > 0) {
+ dir = path.slice(0, path.lastIndexOf("/"));
+ }
+ try {
+ FS.stat(dir);
+ } catch (e) {
+ if (e.errno !== ERRNO_CODES.ENOENT) { // 'ENOENT', see https://github.com/emscripten-core/emscripten/blob/master/system/lib/libc/musl/arch/emscripten/bits/errno.h
+ throw e;
+ }
+ FS.mkdirTree(dir);
+ }
+ // With memory growth, canOwn should be false.
+ FS.writeFile(path, new Uint8Array(buffer), {'flags': 'wx+'});
+}
+
+Module.drop_handler = (function() {
+ var upload = [];
+ var uploadPromises = [];
+ var uploadCallback = null;
+
+ function readFilePromise(entry, path) {
+ return new Promise(function(resolve, reject) {
+ entry.file(function(file) {
+ var reader = new FileReader();
+ reader.onload = function() {
+ var f = {
+ "path": file.relativePath || file.webkitRelativePath,
+ "name": file.name,
+ "type": file.type,
+ "size": file.size,
+ "data": reader.result
+ };
+ if (!f['path'])
+ f['path'] = f['name'];
+ upload.push(f);
+ resolve()
+ };
+ reader.onerror = function() {
+ console.log("Error reading file");
+ reject();
+ }
+
+ reader.readAsArrayBuffer(file);
+
+ }, function(err) {
+ console.log("Error!");
+ reject();
+ });
+ });
+ }
+
+ function readDirectoryPromise(entry) {
+ return new Promise(function(resolve, reject) {
+ var reader = entry.createReader();
+ reader.readEntries(function(entries) {
+ for (var i = 0; i < entries.length; i++) {
+ var ent = entries[i];
+ if (ent.isDirectory) {
+ uploadPromises.push(readDirectoryPromise(ent));
+ } else if (ent.isFile) {
+ uploadPromises.push(readFilePromise(ent));
+ }
+ }
+ resolve();
+ });
+ });
+ }
+
+ function processUploadsPromises(resolve, reject) {
+ if (uploadPromises.length == 0) {
+ resolve();
+ return;
+ }
+ uploadPromises.pop().then(function() {
+ setTimeout(function() {
+ processUploadsPromises(resolve, reject);
+ //processUploadsPromises.bind(null, resolve, reject)
+ }, 0);
+ });
+ }
+
+ function dropFiles(files) {
+ var args = files || [];
+ var argc = args.length;
+ var argv = stackAlloc((argc + 1) * 4);
+ for (var i = 0; i < argc; i++) {
+ HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i]);
+ }
+ HEAP32[(argv >> 2) + argc] = 0;
+ // Defined in display_server_javascript.cpp
+ ccall('_drop_files_callback', 'void', ['number', 'number'], [argv, argc]);
+ }
+
+ return function(ev) {
+ ev.preventDefault();
+ if (ev.dataTransfer.items) {
+ // Use DataTransferItemList interface to access the file(s)
+ for (var i = 0; i < ev.dataTransfer.items.length; i++) {
+ const item = ev.dataTransfer.items[i];
+ var entry = null;
+ if ("getAsEntry" in item) {
+ entry = item.getAsEntry();
+ } else if ("webkitGetAsEntry" in item) {
+ entry = item.webkitGetAsEntry();
+ }
+ if (!entry) {
+ console.error("File upload not supported");
+ } else if (entry.isDirectory) {
+ uploadPromises.push(readDirectoryPromise(entry));
+ } else if (entry.isFile) {
+ uploadPromises.push(readFilePromise(entry));
+ } else {
+ console.error("Unrecognized entry...", entry);
+ }
+ }
+ } else {
+ console.error("File upload not supported");
+ }
+ uploadCallback = new Promise(processUploadsPromises).then(function() {
+ const DROP = "/tmp/drop-" + parseInt(Math.random() * Math.pow(2, 31)) + "/";
+ var drops = [];
+ var files = [];
+ upload.forEach((elem) => {
+ var path = elem['path'];
+ Module['copyToFS'](DROP + path, elem['data']);
+ var idx = path.indexOf("/");
+ if (idx == -1) {
+ // Root file
+ drops.push(DROP + path);
+ } else {
+ // Subdir
+ var sub = path.substr(0, idx);
+ idx = sub.indexOf("/");
+ if (idx < 0 && drops.indexOf(DROP + sub) == -1) {
+ drops.push(DROP + sub);
+ }
+ }
+ files.push(DROP + path);
+ });
+ uploadPromises = [];
+ upload = [];
+ dropFiles(drops);
+ var dirs = [DROP.substr(0, DROP.length -1)];
+ files.forEach(function (file) {
+ FS.unlink(file);
+ var dir = file.replace(DROP, "");
+ var idx = dir.lastIndexOf("/");
+ while (idx > 0) {
+ dir = dir.substr(0, idx);
+ if (dirs.indexOf(DROP + dir) == -1) {
+ dirs.push(DROP + dir);
+ }
+ idx = dir.lastIndexOf("/");
+ }
+ });
+ // Remove dirs.
+ dirs = dirs.sort(function(a, b) {
+ var al = (a.match(/\//g) || []).length;
+ var bl = (b.match(/\//g) || []).length;
+ if (al > bl)
+ return -1;
+ else if (al < bl)
+ return 1;
+ return 0;
+ });
+ dirs.forEach(function(dir) {
+ FS.rmdir(dir);
+ });
+ });
+ }
+})();