summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikolaj Boc <[email protected]>2022-12-30 13:41:40 +0100
committerMikolaj Boc <[email protected]>2023-01-13 21:07:14 +0100
commit2e97ccc8d0e3c1fa0fe34e01d1d3e6f8cd7465ba (patch)
tree4a5094bb2cc1b700c2884e2b1a32226110b7ba45
parent4dbb07f614c914e78437aacf7a1716f632da5e8a (diff)
Add QString<->emscripten::val conversion functions
Following the QRect, add functions converting the QString to native emscripten::val and back: fromJsString, toJsString Change-Id: I2d0625ede3bbf7249e2e91b8de298b5b91df8ba2 Reviewed-by: Morten Johan Sørvig <[email protected]>
-rw-r--r--src/corelib/kernel/qcore_wasm.cpp52
-rw-r--r--src/corelib/text/qstring.h5
-rw-r--r--src/plugins/platforms/wasm/CMakeLists.txt1
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp19
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp1
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp1
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp7
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp3
-rw-r--r--src/plugins/platforms/wasm/qwasmservices.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmstring.cpp36
-rw-r--r--src/plugins/platforms/wasm/qwasmstring.h19
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp1
-rw-r--r--tests/auto/corelib/text/qstring/CMakeLists.txt3
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp11
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring_wasm.cpp28
15 files changed, 115 insertions, 77 deletions
diff --git a/src/corelib/kernel/qcore_wasm.cpp b/src/corelib/kernel/qcore_wasm.cpp
index d7135840fb4..79b5b01cc16 100644
--- a/src/corelib/kernel/qcore_wasm.cpp
+++ b/src/corelib/kernel/qcore_wasm.cpp
@@ -42,4 +42,56 @@ emscripten::val QRectF::toDOMRect() const
return emscripten::val::global("DOMRect").new_(left(), top(), width(), height());
}
+/*!
+ Converts the \l {https://262.ecma-international.org/#sec-string-object}{ECMAScript string} \a
+ jsString to QString. Behavior is undefined if the provided parameter is not a string.
+
+ \since 6.6
+ \ingroup platform-type-conversions
+
+ \sa toJsString()
+*/
+QString QString::fromJsString(emscripten::val jsString)
+{
+ Q_ASSERT_X(jsString.isString(), Q_FUNC_INFO, "Passed object is not a string");
+
+ const double length = jsString["length"].as<double>();
+
+ Q_ASSERT_X((double(uint64_t(length)) != double(uint64_t(length) - 1)
+ && double(uint64_t(length)) != double(uint64_t(length) + 1))
+ || !std::numeric_limits<double>::is_iec559,
+ Q_FUNC_INFO, "The floating-point length cannot precisely represent an integer");
+
+ constexpr int zeroTerminatorLength = 1;
+ const auto lengthOfUtf16 = (length + zeroTerminatorLength) * 2;
+
+ Q_ASSERT_X((double(uint64_t(lengthOfUtf16)) != double(uint64_t(lengthOfUtf16) - 1)
+ && double(uint64_t(lengthOfUtf16)) != double(uint64_t(lengthOfUtf16) + 1))
+ || !std::numeric_limits<double>::is_iec559,
+ Q_FUNC_INFO,
+ "The floating-point lengthOfUtf16 cannot precisely represent an integer");
+
+ const QString result(uint64_t(length), Qt::Uninitialized);
+
+ static const emscripten::val stringToUTF16(emscripten::val::module_property("stringToUTF16"));
+ stringToUTF16(jsString, emscripten::val(quintptr(result.data())),
+ emscripten::val(lengthOfUtf16));
+ return result;
+}
+
+/*!
+ Converts this object to an
+ \l {https://262.ecma-international.org/#sec-string-object}{ECMAScript string}.
+
+ \since 6.6
+ \ingroup platform-type-conversions
+
+ \sa fromJsString()
+*/
+emscripten::val QString::toJsString() const
+{
+ static const emscripten::val UTF16ToString(emscripten::val::module_property("UTF16ToString"));
+ return UTF16ToString(emscripten::val(quintptr(utf16())));
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index bde7041eef9..91a9c869940 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -806,6 +806,11 @@ public:
NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+ static QString fromJsString(emscripten::val jsString);
+ emscripten::val toJsString() const;
+#endif
+
inline bool isNull() const { return d->isNull(); }
diff --git a/src/plugins/platforms/wasm/CMakeLists.txt b/src/plugins/platforms/wasm/CMakeLists.txt
index 15892617ca2..8902597001c 100644
--- a/src/plugins/platforms/wasm/CMakeLists.txt
+++ b/src/plugins/platforms/wasm/CMakeLists.txt
@@ -31,7 +31,6 @@ qt_internal_add_plugin(QWasmIntegrationPlugin
qwasmplatform.cpp qwasmplatform.h
qwasmscreen.cpp qwasmscreen.h
qwasmservices.cpp qwasmservices.h
- qwasmstring.cpp qwasmstring.h
qwasmstylepixmaps_p.h
qwasmtheme.cpp qwasmtheme.h
qwasmwindow.cpp qwasmwindow.h
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index d6343e9f6bc..24523aacbf6 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -3,7 +3,7 @@
#include "qwasmclipboard.h"
#include "qwasmwindow.h"
-#include "qwasmstring.h"
+
#include <private/qstdweb_p.h>
#include <emscripten.h>
@@ -27,12 +27,11 @@ static void commonCopyEvent(val event)
// doing it this way seems to sanitize the text better that calling data() like down below
if (_mimes->hasText()) {
- event["clipboardData"].call<void>("setData", val("text/plain")
- , QWasmString::fromQString(_mimes->text()));
+ event["clipboardData"].call<void>("setData", val("text/plain"),
+ _mimes->text().toJsString());
}
if (_mimes->hasHtml()) {
- event["clipboardData"].call<void>("setData", val("text/html")
- , QWasmString::fromQString(_mimes->html()));
+ event["clipboardData"].call<void>("setData", val("text/html"), _mimes->html().toJsString());
}
for (auto mimetype : _mimes->formats()) {
@@ -40,8 +39,8 @@ static void commonCopyEvent(val event)
continue;
QByteArray ba = _mimes->data(mimetype);
if (!ba.isEmpty())
- event["clipboardData"].call<void>("setData", QWasmString::fromQString(mimetype)
- , val(ba.constData()));
+ event["clipboardData"].call<void>("setData", mimetype.toJsString(),
+ val(ba.constData()));
}
event.call<void>("preventDefault");
@@ -140,7 +139,7 @@ static void qClipboardPasteTo(val dataTransfer)
|| itemMimeType.contains("TEXT", Qt::CaseSensitive)) {
break;
}
- const QString data = QWasmString::toQString(
+ const QString data = QString::fromJsString(
clipboardData.call<val>("getData", val(itemMimeType.toStdString())));
if (!data.isEmpty()) {
@@ -329,12 +328,12 @@ void QWasmClipboard::writeToClipboardApi()
// we have a blob, now create a ClipboardItem
emscripten::val type = emscripten::val::array();
- type.set("type", val(QWasmString::fromQString(mimetype)));
+ type.set("type", mimetype.toJsString());
emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
emscripten::val clipboardItemObject = emscripten::val::object();
- clipboardItemObject.set(val(QWasmString::fromQString(mimetype)), contentBlob);
+ clipboardItemObject.set(mimetype.toJsString(), contentBlob);
val clipboardItemData = val::global("ClipboardItem").new_(clipboardItemObject);
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
index e159b8fe7db..2fc82bfcdc4 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -3,7 +3,6 @@
#include "qwasmcursor.h"
#include "qwasmscreen.h"
-#include "qwasmstring.h"
#include <QtCore/qdebug.h>
#include <QtGui/qwindow.h>
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 3f3e8da3f16..395c9c3ee0e 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -6,7 +6,6 @@
#include "qwasmcompositor.h"
#include "qwasmintegration.h"
#include "qwasmclipboard.h"
-#include "qwasmstring.h"
#include "qwasmcursor.h"
#include <QtGui/qevent.h>
#include <qpa/qwindowsysteminterface.h>
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 4c6f1b14c84..fa4ae981bb5 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -11,7 +11,6 @@
#include "qwasmaccessibility.h"
#include "qwasmservices.h"
#include "qwasmoffscreensurface.h"
-#include "qwasmstring.h"
#include "qwasmwindow.h"
#include "qwasmbackingstore.h"
@@ -287,7 +286,8 @@ void QWasmIntegration::removeScreen(const emscripten::val &element)
auto it = std::find_if(m_screens.begin(), m_screens.end(),
[&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(element); });
if (it == m_screens.end()) {
- qWarning() << "Attempting to remove non-existing screen for element" << QWasmString::toQString(element["id"]);;
+ qWarning() << "Attempting to remove non-existing screen for element"
+ << QString::fromJsString(element["id"]);
return;
}
it->second->deleteScreen();
@@ -299,7 +299,8 @@ void QWasmIntegration::resizeScreen(const emscripten::val &element)
auto it = std::find_if(m_screens.begin(), m_screens.end(),
[&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(element); });
if (it == m_screens.end()) {
- qWarning() << "Attempting to resize non-existing screen for element" << QWasmString::toQString(element["id"]);;
+ qWarning() << "Attempting to resize non-existing screen for element"
+ << QString::fromJsString(element["id"]);
return;
}
it->second->updateQScreenAndCanvasRenderSize();
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 3300449ae46..fd3d83b614a 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -6,7 +6,6 @@
#include "qwasmeventtranslator.h"
#include "qwasmcompositor.h"
#include "qwasmintegration.h"
-#include "qwasmstring.h"
#include "qwasmcssstyle.h"
#include <emscripten/bind.h>
@@ -194,7 +193,7 @@ qreal QWasmScreen::devicePixelRatio() const
QString QWasmScreen::name() const
{
- return QWasmString::toQString(m_shadowContainer["id"]);
+ return QString::fromJsString(m_shadowContainer["id"]);
}
QPlatformCursor *QWasmScreen::cursor() const
diff --git a/src/plugins/platforms/wasm/qwasmservices.cpp b/src/plugins/platforms/wasm/qwasmservices.cpp
index b9f48090e1b..f5fd4e4790f 100644
--- a/src/plugins/platforms/wasm/qwasmservices.cpp
+++ b/src/plugins/platforms/wasm/qwasmservices.cpp
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qwasmservices.h"
-#include "qwasmstring.h"
#include <QtCore/QUrl>
#include <QtCore/QDebug>
@@ -13,8 +12,8 @@ QT_BEGIN_NAMESPACE
bool QWasmServices::openUrl(const QUrl &url)
{
- emscripten::val jsUrl = QWasmString::fromQString(url.toString());
- emscripten::val::global("window").call<void>("open", jsUrl, emscripten::val("_blank"));
+ emscripten::val::global("window").call<void>("open", url.toString().toJsString(),
+ emscripten::val("_blank"));
return true;
}
diff --git a/src/plugins/platforms/wasm/qwasmstring.cpp b/src/plugins/platforms/wasm/qwasmstring.cpp
deleted file mode 100644
index 3de84afef32..00000000000
--- a/src/plugins/platforms/wasm/qwasmstring.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#include "qwasmstring.h"
-
-QT_BEGIN_NAMESPACE
-
-using namespace emscripten;
-
-val QWasmString::fromQString(const QString &str)
-{
- static const val UTF16ToString(
- val::module_property("UTF16ToString"));
-
- auto ptr = quintptr(str.utf16());
- return UTF16ToString(val(ptr));
-}
-
-QString QWasmString::toQString(const val &v)
-{
- QString result;
- if (!v.isString())
- return result;
-
- static const val stringToUTF16(
- val::module_property("stringToUTF16"));
- static const val length("length");
-
- int len = v[length].as<int>();
- result.resize(len);
- auto ptr = quintptr(result.utf16());
- stringToUTF16(v, val(ptr), val((len + 1) * 2));
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmstring.h b/src/plugins/platforms/wasm/qwasmstring.h
deleted file mode 100644
index 62927ee93cb..00000000000
--- a/src/plugins/platforms/wasm/qwasmstring.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#pragma once
-
-#include <qstring.h>
-
-#include <emscripten/val.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWasmString
-{
-public:
- static emscripten::val fromQString(const QString &str);
- static QString toQString(const emscripten::val &v);
-};
-QT_END_NAMESPACE
-
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index aa229b5776a..a8f577cfeae 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -18,7 +18,6 @@
#include "qwasmcompositor.h"
#include "qwasmevent.h"
#include "qwasmeventdispatcher.h"
-#include "qwasmstring.h"
#include "qwasmaccessibility.h"
#include <iostream>
diff --git a/tests/auto/corelib/text/qstring/CMakeLists.txt b/tests/auto/corelib/text/qstring/CMakeLists.txt
index c3f8bbb717c..d3db36e813b 100644
--- a/tests/auto/corelib/text/qstring/CMakeLists.txt
+++ b/tests/auto/corelib/text/qstring/CMakeLists.txt
@@ -9,6 +9,9 @@ if(APPLE)
list(APPEND tst_qstring_extra_libraries ${FWFoundation})
list(APPEND tst_qstring_extra_sources tst_qstring_mac.mm)
endif()
+if(WASM)
+ list(APPEND tst_qstring_extra_sources tst_qstring_wasm.cpp)
+endif()
foreach(test tst_qstring tst_qstring_restricted_ascii)
qt_internal_add_test(${test}
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index aec2d2897a4..2e733fc49bd 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -541,6 +541,7 @@ private slots:
#endif
void STL();
void macTypes();
+ void wasmTypes();
void isEmpty();
void isNull();
void nullness();
@@ -1344,6 +1345,16 @@ void tst_QString::macTypes()
#endif
}
+void tst_QString::wasmTypes()
+{
+#ifndef Q_OS_WASM
+ QSKIP("This is a WASM-only test");
+#else
+ extern void tst_QString_wasmTypes(); // in qcore_wasm.cpp
+ tst_QString_wasmTypes();
+#endif
+}
+
void tst_QString::truncate()
{
QString nullStr;
diff --git a/tests/auto/corelib/text/qstring/tst_qstring_wasm.cpp b/tests/auto/corelib/text/qstring/tst_qstring_wasm.cpp
new file mode 100644
index 00000000000..df5ebddc965
--- /dev/null
+++ b/tests/auto/corelib/text/qstring/tst_qstring_wasm.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtCore/QString>
+#include <QTest>
+
+#include <emscripten/val.h>
+
+void tst_QString_wasmTypes()
+{
+ // QString <-> emscripten::val
+ {
+ QString qtString("test string");
+ const emscripten::val jsString = qtString.toJsString();
+ QString qtStringCopy(qtString);
+ qtString = qtString.toUpper(); // modify
+ QCOMPARE(QString::fromJsString(jsString), qtStringCopy);
+ }
+ {
+ QString longString;
+ for (uint64_t i = 0; i < 1000; ++i)
+ longString += "Lorem ipsum FTW";
+ const emscripten::val jsString = longString.toJsString();
+ QString qtStringCopy(longString);
+ longString = longString.toUpper(); // modify
+ QCOMPARE(QString::fromJsString(jsString), qtStringCopy);
+ }
+}