diff options
author | Alex Shaw <alex.shaw.as@gmail.com> | 2021-04-25 17:57:37 -0400 |
---|---|---|
committer | Alex Shaw <alex.shaw.as@gmail.com> | 2021-05-01 17:26:00 -0400 |
commit | 3464655f5e2adaa1aed8925a9a54b8fb5f238f31 (patch) | |
tree | ebb7c46c7d4f1af6e4b1853a74d7502fee3c450f /src/qml/jsapi | |
parent | 689522817dc559056f7c55f811a189c4821b7787 (diff) |
Add QJSEngine::registerModule
Some applications that use JavaScript as a scripting language may want
to extend JS through C++ code. The current way to do that is with
global objects.
ES6 provides a better way of encapsulating code: modules.
registerModule() allows an application to provide a QJSValue as a named module.
Developers familiar with Node.js will find this very easy to use.
Example:
```c++
QJSValue num(666);
myEngine.registerModule("themarkofthebeast", num);
```
```js
import badnews from "themarkofthebeast";
```
[ChangeLog][QtQml][QJSEngine] Adds the ability to register QJSValues in
C++ as modules for importing in MJS files.
Change-Id: I0c98dcb746aa2aa15aa2ab3082129d106413a23b
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 73 | ||||
-rw-r--r-- | src/qml/jsapi/qjsengine.h | 1 |
2 files changed, 74 insertions, 0 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index b27c6add75..7e8effda45 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -150,6 +150,46 @@ Q_DECLARE_METATYPE(QList<int>) } \endcode + Modules don't have to be files. They can be values registered with + QJSEngine::registerModule(): + + \code + import version from "version"; + + export function getVersion() + { + return version; + } + \endcode + + \code + QJSValue version(610); + myEngine.registerModule("version", version); + QJSValue module = myEngine.importModule("./myprint.mjs"); + QJSValue getVersion = module.property("getVersion"); + QJSValue result = getVersion.call(); + \endcode + + Named exports are supported, but because they are treated as members of an + object, the default export must be an ECMAScript object. Most of the newXYZ + functions in QJSValue will return an object. + + \code + QJSValue name("Qt6"); + QJSValue obj = myEngine.newObject(); + obj.setProperty("name", name); + myEngine.registerModule("info", obj); + \endcode + + \code + import { name } from "info"; + + export function getName() + { + return name; + } + \endcode + \section1 Engine Configuration The globalObject() function returns the \b {Global Object} @@ -555,6 +595,8 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in \note If an exception is thrown during the loading of the module, the return value will be the exception (typically an \c{Error} object; see QJSValue::isError()). + \sa registerModule() + \since 5.12 */ QJSValue QJSEngine::importModule(const QString &fileName) @@ -577,6 +619,37 @@ QJSValue QJSEngine::importModule(const QString &fileName) } /*! + Register a QJSValue to serve as a module. After this function is called, + all modules that import \a moduleName will import the value of \a value + instead of loading \a moduleName from the filesystem. + + Any valid QJSValue can be registered, but named exports (i.e. + \c {import { name } from "info"} are treated as members of an object, so + the default export must be created with one of the newXYZ methods of + QJSEngine. + + Because this allows modules that do not exist on the filesystem to be imported, + scripting applications can use this to provide built-in modules, similar to + Node.js + + \note The QJSValue \a value is not called or read until it is used by another module. + This means that there is no code to evaluate, so no errors will be seen until + another module throws an exception while trying to load this module. + + \warning Attempting to access a named export from a QJSValue that is not an + object will trigger a \l{Script Exception}{exception}. + + \sa importModule() + */ +bool QJSEngine::registerModule(const QString &moduleName, const QJSValue &value) +{ + m_v4Engine->registerModule(moduleName, value); + if (m_v4Engine->hasException) + return false; + return true; +} + +/*! Creates a JavaScript object of class Object. The prototype of the created object will be the Object diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h index ac79b30ebc..84730afe2b 100644 --- a/src/qml/jsapi/qjsengine.h +++ b/src/qml/jsapi/qjsengine.h @@ -71,6 +71,7 @@ public: QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1, QStringList *exceptionStackTrace = nullptr); QJSValue importModule(const QString &fileName); + bool registerModule(const QString &moduleName, const QJSValue &value); QJSValue newObject(); QJSValue newSymbol(const QString &name); |