diff options
Diffstat (limited to 'src/corelib/platform/wasm/qstdweb_p.h')
-rw-r--r-- | src/corelib/platform/wasm/qstdweb_p.h | 274 |
1 files changed, 219 insertions, 55 deletions
diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h index 75c2ec34b1..a3b5bd5b6b 100644 --- a/src/corelib/platform/wasm/qstdweb_p.h +++ b/src/corelib/platform/wasm/qstdweb_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSTDWEB_P_H #define QSTDWEB_P_H @@ -51,17 +15,36 @@ // We mean it. // -#include <qglobal.h> +#include <private/qglobal_p.h> +#include <QtCore/qglobal.h> +#include "QtCore/qhash.h" +#include "QtCore/qiodevice.h" + #include <emscripten/val.h> + #include <cstdint> #include <functional> +#include <initializer_list> +#include <memory> +#include <string> +#include <utility> + +#if QT_CONFIG(thread) +#include <emscripten/proxying.h> +#include <emscripten/threading.h> +#endif // #if QT_CONFIG(thread) QT_BEGIN_NAMESPACE +class QMimeData; + namespace qstdweb { + extern const char makeContextfulPromiseFunctionName[]; // DOM API in C++, implemented using emscripten val.h and bind.h. - // This is private API and can be extened and changed as needed. + // This is private API and can be extended and changed as needed. + // The API mirrors that of the native API, with some extensions + // to ease usage from C++ code. class ArrayBuffer; class Blob; @@ -71,40 +54,84 @@ namespace qstdweb { class Uint8Array; class EventCallback; - class ArrayBuffer { + class Q_CORE_EXPORT ArrayBuffer { public: + explicit ArrayBuffer(uint32_t size); explicit ArrayBuffer(const emscripten::val &arrayBuffer); uint32_t byteLength() const; + ArrayBuffer slice(uint32_t begin, uint32_t end) const; + emscripten::val val() const; private: friend class Uint8Array; emscripten::val m_arrayBuffer = emscripten::val::undefined(); }; - class Blob { + class Q_CORE_EXPORT Blob { public: explicit Blob(const emscripten::val &blob); + static Blob fromArrayBuffer(const ArrayBuffer &arrayBuffer); uint32_t size() const; + static Blob copyFrom(const char *buffer, uint32_t size, std::string mimeType); + static Blob copyFrom(const char *buffer, uint32_t size); + Blob slice(uint32_t begin, uint32_t end) const; + ArrayBuffer arrayBuffer_sync() const; + emscripten::val val() const; + std::string type() const; private: friend class FileReader; emscripten::val m_blob = emscripten::val::undefined(); }; - class File { + class Q_CORE_EXPORT File { public: File() = default; explicit File(const emscripten::val &file); + ~File(); + + File(const File &other); + File(File &&other); + File &operator=(const File &other); + File &operator=(File &&other); Blob slice(uint64_t begin, uint64_t end) const; std::string name() const; uint64_t size() const; + std::string type() const; + void stream(uint32_t offset, uint32_t length, char *buffer, + std::function<void()> completed) const; + void stream(char *buffer, std::function<void()> completed) const; + emscripten::val val() const; + void fileUrlRegistration() const; + const QString &fileUrlPath() const { return m_urlPath; } + emscripten::val file() const { return m_file; } private: emscripten::val m_file = emscripten::val::undefined(); + QString m_urlPath; }; - class FileList { + class Q_CORE_EXPORT FileUrlRegistration + { + public: + explicit FileUrlRegistration(File file); + ~FileUrlRegistration(); + + FileUrlRegistration(const FileUrlRegistration &other) = delete; + FileUrlRegistration(FileUrlRegistration &&other); + FileUrlRegistration &operator=(const FileUrlRegistration &other) = delete; + FileUrlRegistration &operator=(FileUrlRegistration &&other); + + const QString &path() const { return m_path; } + + private: + QString m_path; + }; + + using FileUrlRegistrations = std::vector<std::unique_ptr<FileUrlRegistration>>; + + class Q_CORE_EXPORT FileList { public: FileList() = default; explicit FileList(const emscripten::val &fileList); @@ -112,19 +139,21 @@ namespace qstdweb { int length() const; File item(int index) const; File operator[](int index) const; + emscripten::val val() const; private: emscripten::val m_fileList = emscripten::val::undefined(); }; - class FileReader { + class Q_CORE_EXPORT FileReader { public: ArrayBuffer result() const; void readAsArrayBuffer(const Blob &blob) const; - void onLoad(const std::function<void ()> &onLoad); - void onError(const std::function<void ()> &onError); - void onAbort(const std::function<void ()> &onAbort); + void onLoad(const std::function<void(emscripten::val)> &onLoad); + void onError(const std::function<void(emscripten::val)> &onError); + void onAbort(const std::function<void(emscripten::val)> &onAbort); + emscripten::val val() const; private: emscripten::val m_fileReader = emscripten::val::global("FileReader").new_(); @@ -133,35 +162,170 @@ namespace qstdweb { std::unique_ptr<EventCallback> m_onAbort; }; - class Uint8Array { + class Q_CORE_EXPORT Uint8Array { public: static Uint8Array heap(); explicit Uint8Array(const emscripten::val &uint8Array); explicit Uint8Array(const ArrayBuffer &buffer); + explicit Uint8Array(uint32_t size); Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length); - Uint8Array(char *buffer, uint32_t size); + Uint8Array(const char *buffer, uint32_t size); ArrayBuffer buffer() const; uint32_t length() const; void set(const Uint8Array &source); + Uint8Array subarray(uint32_t begin, uint32_t end); void copyTo(char *destination) const; + QByteArray copyToQByteArray() const; + static void copy(char *destination, const Uint8Array &source); + static Uint8Array copyFrom(const char *buffer, uint32_t size); + static Uint8Array copyFrom(const QByteArray &buffer); + emscripten::val val() const; + private: static emscripten::val heap_(); static emscripten::val constructor_(); emscripten::val m_uint8Array = emscripten::val::undefined(); }; - class EventCallback + class Q_CORE_EXPORT EventCallback + { + public: + EventCallback() = default; + ~EventCallback(); + EventCallback(EventCallback const&) = delete; + EventCallback& operator=(EventCallback const&) = delete; + EventCallback(emscripten::val element, const std::string &name, + const std::function<void(emscripten::val)> &fn); + + private: + emscripten::val m_element = emscripten::val::undefined(); + std::string m_eventName; + std::unique_ptr<std::function<void(emscripten::val)>> m_handler; + emscripten::val m_eventListener = emscripten::val::undefined(); + }; + + struct PromiseCallbacks + { + std::function<void(emscripten::val)> thenFunc; + std::function<void(emscripten::val)> catchFunc; + std::function<void()> finallyFunc; + }; + + namespace Promise { + void Q_CORE_EXPORT adoptPromise(emscripten::val promise, PromiseCallbacks callbacks); + + template<typename... Args> + void make(emscripten::val target, + QString methodName, + PromiseCallbacks callbacks, + Args... args) + { + emscripten::val promiseObject = target.call<emscripten::val>( + methodName.toStdString().c_str(), std::forward<Args>(args)...); + if (promiseObject.isUndefined() || promiseObject["constructor"]["name"].as<std::string>() != "Promise") { + qFatal("This function did not return a promise"); + } + + adoptPromise(std::move(promiseObject), std::move(callbacks)); + } + + void Q_CORE_EXPORT all(std::vector<emscripten::val> promises, PromiseCallbacks callbacks); + }; + + template<class F> + decltype(auto) bindForever(F wrappedCallback) + { + return wrappedCallback; + } + + class Q_CORE_EXPORT BlobIODevice: public QIODevice { public: - EventCallback(emscripten::val element, const std::string &name, const std::function<void ()> &fn); - static void activate(emscripten::val event); + BlobIODevice(Blob blob); + bool open(QIODeviceBase::OpenMode mode) override; + bool isSequential() const override; + qint64 size() const override; + bool seek(qint64 pos) override; + + protected: + qint64 readData(char *data, qint64 maxSize) override; + qint64 writeData(const char *, qint64) override; + private: - static std::string contextPropertyName(const std::string &eventName); - std::function<void ()> m_fn; + Blob m_blob; }; + + class Uint8ArrayIODevice: public QIODevice + { + public: + Uint8ArrayIODevice(Uint8Array array); + bool open(QIODevice::OpenMode mode) override; + bool isSequential() const override; + qint64 size() const override; + bool seek(qint64 pos) override; + + protected: + qint64 readData(char *data, qint64 maxSize) override; + qint64 writeData(const char *data, qint64 size) override; + + private: + Uint8Array m_array; + }; + + inline emscripten::val window() + { + static emscripten::val savedWindow = emscripten::val::global("window"); + return savedWindow; + } + + bool haveAsyncify(); + bool Q_CORE_EXPORT haveJspi(); + bool canBlockCallingThread(); + + struct CancellationFlag + { + }; + +#if QT_CONFIG(thread) + template<class T> + T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue) + { + T result; + queue->proxySync(emscripten_main_runtime_thread_id(), + [task, result = &result]() { *result = task(); }); + return result; + } + + template<> + inline void proxyCall<void>(std::function<void()> task, emscripten::ProxyingQueue *queue) + { + queue->proxySync(emscripten_main_runtime_thread_id(), task); + } + + template<class T> + T runTaskOnMainThread(std::function<T()> task, emscripten::ProxyingQueue *queue) + { + return emscripten_is_main_runtime_thread() ? task() : proxyCall<T>(std::move(task), queue); + } + + template<class T> + T runTaskOnMainThread(std::function<T()> task) + { + emscripten::ProxyingQueue singleUseQueue; + return runTaskOnMainThread<T>(task, &singleUseQueue); + } + +#else + template<class T> + T runTaskOnMainThread(std::function<T()> task) + { + return task(); + } +#endif // QT_CONFIG(thread) + } QT_END_NAMESPACE |