[Interest] How to set a QJSValue with functions as a context property in QQmlContext?

Richard Weickelt richard at weickelt.de
Wed Apr 15 17:33:55 CEST 2020


> OK, that does paint a different picture. The feature you are asking for,
> then, is for QJSEngine to allow defining ECMAScript modules from C++, that
> can be imported in your JavaScript files via standard ECMAScript "import"
> statements. I would not be automatically opposed to such a feature.

That's an interesting idea. How could such an API look like?
QJSEngine::registerModule(uri, QJSValue module)

> 
> However, as all of your code seems to be JavaScript anyway, why don't you
> write everything as real ECMAScript modules in the first place? 

What do you have in mind?

> AFAICS the
> C++ code in your example is only used for plumbing. Is that so?

It is mostly about plumbing. But there is a little bit more. How much do you
know about Qbs? The user does usually not write .js files, but .qbs files
which look almost like QML. See
https://doc.qt.io/qbs/language-introduction.html for examples. Those .qbs
files cannot be loaded/evaluated directly by the QML engine. They need to be
evaluated in steps and we follow a lazy evaluation approach. We analyse the
structure first, then start to evaluate certain properties, for instance the
"name" and "condition" property of a product item. On the RHS of these
properties, the user might access other properties of the product or some
other special items like "project". To do so, we intercept property read
access. If the code under current evaluation accesses a property that has
not been evaluated yet, we start evaluation now. This way we can:

- be flexible and expand our item tree as we have evaluated more properties
- create a property dependency graph and know when we need to rebuild
certain parts of the project
- detect cycles

If my C++-defined ECMAScript modules would be QObjects under the hood, then
I could use a slightly modified QQmlOpenMetaObject to intercept property
read access. Or will there be an easier way in Qt6?

> 
>> The final goal is to port the scripting backend of Qbs from QtScript over to
>> the V4 engine, but I am still at the very beginning. Although Qbs files look
>> like QML, we are not using the QML machinery. Instead, we use only the QML
>> parser to decompose the document structure and retrieve items and property
>> declarations/assignments. The resulting code snippets (property assignments)
>> are then evaluated in different contexts. We have different context levels,
>> e.g. a document context for imported JS modules, a product context for
>> properties related to the current product, and a property context where we
>> provide properties like "base" referring to the base class value.
> 
> import * from "documentFooBar"
> import * from "productA"
> import base from "propertySomething"
> 
> The respective .mjs files would be modules that set up the required stuff in
> JavaScript. You can also put import statements into any dynamically
> evaluated JavaScript snippets.
> 
> The nice thing about importing things explicitly is that the JS engine knows
> what is there already when compiling.

That looks indead like what we need. So "productA" would be the module I
have registered via above API?



More information about the Interest mailing list