/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** 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 Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page wasm.html
\title Qt for WebAssembly
\brief Runs Qt applications in a secure sandbox in the browser.

\ingroup experimentalplatform

WebAssembly (or Wasm) is a binary bytecode format intended to be executed
in a virtual machine inside a web browser. This allows an application
to be deployed to a device with a compliant web browser without going
through any installation steps. The application will run inside a
secure sandbox in the web browser. This format is nearly as fast as native machine code,
and is now supported by all major web browsers. This makes it appropriate for
applications that do not need full access to the device capabilities,
but benefits from a swift and uncomplicated installation process.

Qt for WebAssembly is a \l {Qt Platform Abstraction}{platform plugin} that
lets you build Qt applications, which can be integrated into your web pages.
It doesn't require any client-side installations and reduces the server-side
resource usage.

\note Qt for WebAssembly is currently in Tech Preview.

\section1 Getting Started with Qt for WebAssembly

\section2 Install Emscripten

\l{https://emscripten.org/docs/introducing_emscripten/index.html}{emscripten}
is a toolchain for compiling to WebAssembly. It lets you run Qt on the web at
near-native speed without plugins.

Refer to the \l{https://emscripten.org/docs/getting_started/index.html}
{emscripten documentation} for more information about installing the
Emscripten SDK.

After installation, you should have the Emscripten compiler in your path.
Check this with the following command:
\badcode
    em++ --version
\endcode

Each Qt minor version targets a specific minimum Emcsripten version, which will
not change for the lifetime of that Qt minor version. Qt's binary packages are
built using this version of the Emscripten SDK. We recommend installing
the minimum Emcsripten version corresponding to the Qt version you are using,
especially if you are using the binary pckages.

Newer versions of Emscripten above the minimum version may work (and often do),
but may introduce behavior changes which require changes to Qt.

The minimum versions are:
\list
   \li Qt 6.2.0: 2.0.14
\endlist

Use \c emsdk to install specific \c emscripten versions. For example, to install
it for Qt 6.2 enter:
\list
    \li ./emsdk install 2.0.14
    \li ./emsdk activate 2.0.14
\endlist

After installation, on Windows, you should have emscripten in your path.  On macOS or Linux
you need to add it to your path, like this:

\badcode
    source /path/to/emsdk/emsdk_env.sh
\endcode

Check this with the following command:

\badcode
    em++ --version
\endcode

\section3 Download the binaries

The binary builds can be downloaded in the Downloads section using your Qt
account.

\section3 Build Qt from the sources

Alternatively, you could download the Qt sources in the Downloads section,
and build Qt from it.

Configure Qt as a cross-compile build for the \c wasm-emscripten platform.
This will implicitly set the \c -static, \c -no-feature-thread, and \c{-no-make examples}
configure options. Thread support and building of the examples can be enabled
by removing the corresponding disabling option. Shared library builds are not
supported at this time.

You need a host build of the same version of Qt and specify that path in the \e
QT_HOST_PATH CMake variable or by using the \c -qt-host-path configure argument.

Although it should be detected, you may optionally set the
\e{CMAKE_TOOLCHAIN_FILE} CMake variable to the Emscripten.cmake toolchain file
that comes with Emscripten SDK. This can be done by setting the environment
variable \e{CMAKE_TOOLCHAIN_FILE} or by passing
\c{CMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake} to configure.

\badcode
    ./configure -qt-host-path /path/to/Qt -platform wasm-emscripten -prefix $PWD/qtbase
\endcode

On Windows, make sure you have \c MinGW in your \c PATH
and configure with the following:

\badcode
    configure -qt-host-path C:\Path\to\Qt -no-warnings-are-errors -platform wasm-emscripten -prefix %CD%\qtbase
\endcode

Build required modules:

\badcode
    cmake --build . -t qtbase -t qtdeclarative [-t another_module]
\endcode

\section3 Build and run your application


\badcode
   $ /path/to/qt-wasm/qtbase/bin/qt-cmake
   $ make
\endcode

This generates the following files:

\table
    \header
        \li Generated file
        \li Brief Description
    \row
        \li app.html
        \li HTML container
    \row
        \li qtloader.js \li JS API for loading Qt apps
    \row
        \li app.js
        \li JS API for loading Qt apps
    \row
        \li app.wasm
        \li emscripten app binary
\endtable

    When deploying the app, the compression is typically handled on
    the server side. We recommend to compress the wasm binaries because
    this typically reduces the size of the binary by 50 %.

    \sa {WebAssembly Resource site},{Getting Started with Qt for WebAssembly},
        {Remote UIs with WebGL and WebAssembly}

\section3 Additional configuration
    Qt for Webassembly has several additional configuration arguments available.
\table
    \header
        \li Configure Argument
        \li Brief Description
    \row
        \li -sse2
        \li This enables autovectorization and Wasm SIMD support by adding the compiler argument -msimd128. In addition, emulated
        and native optcode SSE instructions are utilized (at which point Qt's SSE code paths will also be used).
        SSE1, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, and 128-bit AVX instructions only. Simd support may need to be enabled
        in browsers advanced configurations, such as 'about:config' or 'chrome:flags'. There may be performance
        issues when used with certain SIMD instructions that are emulated and that have no native optcode supported by the browser.
        For more information see https://emscripten.org/docs/porting/simd.html
    \row
        \li -feature-thread
        \li Multi-threaded wasm
    \row
        \li -device-option QT_WASM_SOURCE_MAP=1
        \li Debugging option for creating source maps
    \row
        \li -feature-opengles3
        \li Use opengles3 in addition to the default opengles2
\endtable

\section1 Test-run your application

You can test-run your application in the following way:

\badcode
    /path/to/emscripten/emrun --browser=firefox appname.html
\endcode


    \section1 Supported target browsers and devices

    \section2 Desktop

    \list
        \li Chrome
        \li Firefox
        \li Safari
        \li Edge(Chrome)
    \endlist

    If the browser supports WebAssembly, then Qt should run.

    \note Qt has a fixed WebGL requirement, also for apps that do not
    use WebGL directly. Browsers often blacklist WebGL for older/unsupported
    GPUs.

    \section2 Mobile

    \list
        \li Android Chrome Browser
        \li iPhone / iPad Mobile Safari
    \endlist

    \note There is currently no support for text input using the virtual
    keyboard. Safari currently does not support wasm modules of the size
    Qt produces.

    Qt does not make direct use of operating system features and it makes
    no difference if, for example, FireFox runs on Windows or macOS. Qt
    does use some operating system adaptations, for example for ctrl/cmd
    key handling on macOS.

    \section1 Supported Qt Modules

    Qt for WebAssembly supports a subset of the Qt modules and features. The
    list below lists the currently tested modules.

    \list
    \li QtBase (see section for limitations below)
    \li QtShaderTools
    \li QtDeclarative (see section for limitations below)
    \li QtQuickControls2
    \li QtWebSockets
    \li QQtSvg
    \li QtMqtt
    \endlist

    \section2 Other modules are untested and may or may not work.

   Note that changes and updates to browsers may also change Wasm platform
   behavior, thus this documentation and listed limitations below may not be
   up-to-date.

   \list
   \li Web browsers get regular updates and they are configurable and
   extensible, sometimes with surprising side effects for
   WebAssembly-based applications:
        \list
        \li JavaScript blockers may block JavaScript without enabling
        NoScript. This means that <noscript> content is not displayed,
        and that the application appears to be stuck at the loading screen.
        \li Some ad-blockers block all .wasm files from specific hosts, such as github.com
        \li privacy.resistFingerprinting=true (FireFox) disables high-dpi support
        - the browser will appear to be running on a standard-dpi display.
        \endlist
   \endlist

    \section2 QtBase limitations and not supported features
    \section3 QtBase on OpenGL Desktop, Vulkan or Metal
    \list
    \li WebGL is required, even for applications which do not use OpenGL themselves. All
    relevant browsers support WebGL, but note that some browsers blacklist certain
    older GPUs. The Qt loader will detect this and display an error message.
    \li Mixing OpenGL and raster content is not supported
    \li Child OpenGL windows are not supported. The window compositor (in the
    Qt for Wasm platform plugin) supports raster windows only.
    \li QOpenGLWidget is not supported: QTBUG-66944
    \li Qt will detect OpenGL support as OpenGL ES. In reality the browser
    will be providing WebGL. WebGL 1.0 is based on OpenGL ES 2, and WebGL 2.0 based on OpenGL ES 3
    are very similar, but there are some incompatibilities. See
    \l {https://www.khronos.org/registry/webgl/specs/latest/1.0/#6}{WebGL and OpenGL Differences}
    There are additional differences between WebGL 1.0 and WebGL 2.0 which are documented in:
    \l {https://www.khronos.org/registry/webgl/specs/latest/2.0}{WebGL 2.0 Specification}
    \endlist

    \section3 Multithreading with QThread, QConcurrent, QFuture as part of QtBase

    Threads on Qt for WebAssembly are not officially supported yet and may not work
    exactly like posix threads do. Refer to \l {https://emscripten.org/docs/porting/pthreads.html}{Pthreads Support}.

    Qt on WebAssembly can run multithreads, however support is disabled by default in
    order to be compatible with as many browsers as possible. Thread support can be
    enabled by building Qt from source and using the "-feature-thread" configure flag.

    The Qt for WebAssembly binary release packages do not support multithreading.

    The minimum Emscripten SDK version is 1.38.30. The Emscripten pthreads documentation
    contains relevant documentation for multithreading.

    Threads are supported by some (but not all) browsers. Configuration changes may
    be required. The [1] demo can be used to determine if thread support is available.
    Note that it is the build mode which determines if browser thread support is required,
    not whether the application starts a thread or not.

    In Firefox versions before 79, open about:config and make sure the following option
    is enabled:
        \list
        \li javascript.options.shared_memory = true
        \endlist

    Thread support will only be enabled provided that that the web server sets two
    additional headers:
    \list
    \li Cross-Origin-Opener-Policy: same-origin
    \li Cross-Origin-Embedder-Policy: require-corp
    \endlist
    (These are the COOP and COEP headers, respectively)

    Mozilla bug 1619649 tracks the Firefox defaults change. In the mean time, its
    possible to manually bypass or enable the header check:

    Firefox Nightly or Beta - bypass header check:
    \list
    \li dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled = true
    \endlist
    Firefox Release - enable header check:
    \list
    \li browser.tabs.remote.useCrossOriginEmbedderPolicy = true
    \li browser.tabs.remote.useCrossOriginOpenerPolicy = true
    \endlist
    After enabling the header check, make sure your web server sets the required headers.
    See \l {https://bugreports.qt.io/browse/QTBUG-79087}{QTBUG-79087} for an example
    python-based development server.

    \section4 https://bugreports.qt.io/browse/QTBUG-79087

    Application developers may need to add two settings to its .pro or CMakeFiles.txt
    file when enabling threads:

    \list
    \li Thread Pool Size: Applications should set the expected number of concurrent
    threads at build time. This can be done by setting QT_WASM_PTHREAD_POOL_SIZE
    in the .pro or CMakeFIles.txt file (maps to Emscripten PTHREAD_POOL_SIZE).
    Applications can exceed PTHREAD_POOL_SIZE, provided they return main thread
    control to the browser before waiting on the new thread, for example by returning
    from the event handler that started the new thread. This allows the browser to
    start another web worker. Immediately waiting for the new thread on the main
    thread (using QThread::wait() or similar) will deadlock. Qt sets
    PTHREAD_POOL_SIZE to 4 by default.
    \li Heap Memory Size: Applications should set the heap memory size at build time,
    since growing the heap is not supported with pthreads enabled. This can be be done
    by setting QT_WASM_INITIAL_MEMORY in the CMakeFiles.txt file
    (maps to Emscripten INITIAL_MEMORY). Browsers typically limit the initial
    WASM memory allocation size to 1GB. Qt sets INITIAL_MEMORY to 1GB by default
    (for -feature-thread enabled builds)
    \endlist

    Using cmake, such as:

    \badcode
        set(QT_WASM_PTHREAD_POOL_SIZE, 10)
    \endcode

    \section3 Limited Network access due to web sandbox

    The web sandbox limits network access to a subset of what is available for native
    apps.

    \list
    \li QNetworkAccessManager http requests to the web page origin server, or to a
    server which supports CORS.
    \li QWebSocket connections to any host.
    \li TCP and UDP socked tunneling using over WebSockets using a websockify server [3].
    \list
    \li Websockify v0.8.0 can be used to tunnel TCP connections with QT5.12 but it is
    \b {MANDATORY} to specify the base64 or binary subprotocols before calling
    QWebSocket::open().
    \endlist
    \endlist

    \section3 Files and local file system access limited due to the web sandbox

    File system access is sandboxed on the web, and this has implications for how the
    application works with files. The Web platform provides APIs for accessing the local
    file system in a way which is under user control, as well as APIs for accessing
    persistent storage. Emscripten and Qt wraps these features and provides APIs which
    are easier to use from C++ and Qt-based applications.

    The web platform provides features for accessing local files and persistent storage:
    \list
    \li <input type="file"> for showing a native open-file dialog where the user can pick a file.
    \li IndexedDB provides persistent local storage (not accessible outside the browser)
    \endlist

    Emscripten provides several file systems with a POSIX like API. These include:
    \list
    \li the MEMFS ephemeral file system which stores files in-memory
    \li the IDBFS persistent file system which stores files using IndexedDB
    \endlist

    Emscripten mounts a temporary MEMFS filesystem to "/" at app startup. This means
    that QFile can be used, and will read and write files to memory by default. Qt
    provides other API as well:
    \list
    \li QSettings has an IndexedDB-based backend; Note that QSettings is
    asynchronous on WebAssembly. See usage example at [2]
    \li \l {https://doc.qt.io/qt-5/qfiledialog.html#getOpenFileContent}{QFileDialog::getOpenFileContent() }
    opens a native file dialog where the user can pick a file
    \li \l {https://doc.qt.io/qt-5/qfiledialog.html#saveFileContent}{QFileDialog::saveFileContent()}
    saves a file to the local file system via file download}
    \endlist

    \section3 Clipboard with only text content

    Qt supports copying and pasting text to the system clipboard but there are browser
    specific differences you need to take into account in your code.
    \list
    \li Browsers that support the Clipboard API are preferred. Note that a requirement for this API
    is that the web page is served over a secure connection (e.g. https).
    \list
        \li Chrome supports the Clipboard API
        \li Firefox supports the Clipboard API behind a flag:
            dom.events.asyncClipboard.dataTransfer
    \endlist
    \li Browsers that will send clipboard events to Qt's canvas element are also
    supported
    \list
        \li This mode supports the CTRL+x/c/v keyboard shortcuts only
        \li Ongoing work. Firefox works well, other browsers have some hiccups.
        \li text only at this time
    \endlist
    \endlist

    \section3 Other QtBase known limitations

    \list
    \li Nested event loops are not supported. Applications should not call, for example, QDialog::exec()
    or create a new QEventLoop object.
    \li Drag and Drop is not supported
    \li Printing is not supported
    \li QDnsLookup lookups, QTcpSocket, QSsl do not work and are not supported on
    Wasm due to the platform sandbox
    \li Accessibility: Wasm as a platform limits the access to canvas and this cannot be
    circumvented by Qt. Qt renders application content to a canvas element, and does not
    use (other) native DOM elements. This means accessibility (screen readers) are not
    supported and that text inputs won't trigger virtual keyboards.
    \li Fonts: Wasm sandbox does not allow access to system fonts. Font files must be
    distributed with the application, for example in Qt resources or downloading.
    Qt for WebAssembly itself embeds one such font.
    \li High-DPI and scaling: High-DPI rendering is supported, and so is setting the
    overall UI visual size using the browser zoom feature. Browser font size
    (and type) settings have no effect on Qt applications.
    \endlist

    \section3 QtQuickControls2 known issues and limitations

    Known limitations and issues with Qt Quick Controls 2:
    \list
    \li There may be artifacts of uninitialized graphics memory on some
    Qt Quick Controls 2 components, such as checkboxes. This can sometimes
    be seen on HighDPi displays.
    \li Native styles for Windows and macOS are not supported as Wasm as a platform
    is not providing that capability
    \endlist

    \section3 Debugging and profiling

    Wasm debugging is done on browser javascript console, debugging applications on Wasm
    directly within Qt Creator is not possible.

    \list
    \li Qt debug and logging output is printed on the JavaScript console, which can be
    accessed via browser "Developer Tools" or similar.
    \li Source maps for stepping through code, can be created by reconfiguring Qt with
    the --device-option QT_WASM_SOURCE_MAP=1, and building a debug build.
    \list
        \li \l {https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map}
        \li \l {https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps#source_maps_in_devtools_sources_panel}
    \endlist
    \li Mobile browsers can use remote debugging
    \list
        \li \l {https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging}
        \li \l {https://developers.google.com/web/tools/chrome-devtools/remote-debugging}
        \li \l {https://developer.apple.com/safari/tools/}
    \endlist
    \li To stop execution on a certain line and popup the browser debugger
    programmatically, you can add the function emscripten_debugger(); to the application
    source code.
    \li Profiling can be accomplished by using a debug build and the javascript console
    profiling features. Qt adds --profiling-funcs to the linker arguments in debug builds,
    which preserve function names in profiling
    \endlist

    \section2 Footprint and file size

    Expected footprint (download size): Wasm modules as produced by the compiler can be
    large, but compress well:

    \table
    \header
        \li Example
        \li gzip
        \li brotli
   \row
        \li helloglwindow (QtCore + QtGui)
        \li 2.8M
        \li 2.1M
    \row
        \li wiggly widget (QtCore + QtGui + QtWidgets)
        \li 4.3M
        \li 3.2M
    \row
        \li SensorTag (QtCore + QtGui + QtWidgets + QtQuick + QtCharts)
        \li 8.6M
        \li 6.3M
    \endtable

    Compression is typically handled on the web server side, using standard compression
    features: the server compresses automatically or picks up pre-compressed versions of the
    files. There's generally no need to have special handling of wasm files.

    \section4 Other known issues, limitations and general notes

    \list
    \li Supported on all development host systems: Linux, MacOS, and Windows (MinGW)
    \li Link time error such as "wasm-ld: error: initial memory too small", requires
    adjustment of the initial memory size. Use QT_WASM_TOTAL_MEMORY to set the initial
    size in kb, which must be a multiple of 64KB (65536).
    In CMakeFiles.txt: set(QT_WASM_TOTAL_MEMORY, xxxxx);
    \li To target WebAssembly platform specifically in qmake, use emscripten as the
    platform name, such as: emscripten { message("Building for WebAssembly") }
    \li Open known bugs and issues on Wasm can be found on Qt issue tracking JIRA on
    this link: \l https://bugreports.qt.io/secure/RapidBoard.jspa?rapidView=258&quickFilter=2352
    \endlist

\section1 Some examples

\list
        \li \l {https://www.qt.io/web-assembly-example-industrial-panel}
               {Industrial Panel Demo}
        \li \l {https://www.qt.io/web-assembly-example-slate}
               {QMainWindow app}
        \li \l {https://www.qt.io/web-assembly-example-gallery}
               {A gallery of available controls in Qt Quick Controls}
        \li \l {https://www.qt.io/web-assembly-example-pizza-shop}
               {Web app for prdering pizzas}
\endlist

\section1 External resources

\list
        \li \l {Qt for WebAssembly Technology Preview}
        \li \l {Qt and WebAssembly}
        \li \l {Qt for WebAssembly wiki}
        \li \l {Getting Started with Qt for WebAssembly}
        \li \l {Remote UIs with WebGL and WebAssembly}
        \li \l {WebAssembly Resource site}
        \li \l {https://emscripten.org/docs/} {Emscripten Documentation}
\endlist

\section1 Licenses

Qt for WebAssembly is available under commercial licenses from \l{The Qt Company}.
In addition, it is available under the \l{GNU General Public License, version 3}.
See \l{Qt Licensing} for further details.
*/
