Details
-
Technical task
-
Resolution: Duplicate
-
P2: Important
Description
There are multiple language features [1] and runtime (QQmlEngine/QQmlObjectCreator) related features that have to be supported by the type compiler. In particular:
Legend:
☐ - not covered. if versioned, like "☐ 6.4", it would mean that it is important to look at this in the scope of the specific Qt release.
☒ - done.
QML language (object definitions specifically*) [2]:
- ☒ Import statements are handled by the generic machinery (qmlcompiler library); comments are not interesting at the moment (and they do not map to C++ at all in general)
- ☒ Types
- Basic/builtin types [3] (mostly related to properties)
- JavaScript types (unclear whether there are any special ones worthy of attention)
- Object types (mostly related to object bindings)
- ☒ id attribute
- Properties
- attributes must map correctly to the C++ model (some require Q_CLASSINFO in C++)
- ☒ default
- ☒ required
- ☒ readonly
- ☒ special types: `var` (QVariant) and `list` (QQmlListProperty/QQmlListReference)
- ☒ attached properties: correctly instantiated to be accessible in JavaScript
- group properties: both references and value types must be handled (differences are visible in bindings)
- ☒ generalized group properties (
QTBUG-105378) - ☒ usual group properties
- ☒ generalized group properties (
- ☒ private properties (Q_PRIVATE_PROPERTY): internal-only but must be supported (QtQuick uses them extensively)
- ☒ special C++ case (no read method): Q_PROPERTY(QByteArray sampler MEMBER sampler)
- ☒ Properties with only BINDABLE (no READ/WRITE/NOTIFY). Reference:
QTBUG-97249
- attributes must map correctly to the C++ model (some require Q_CLASSINFO in C++)
- Aliases
- ☒ methods (read, write, notify/bindable) must forward to the corresponding property methods
- ☒ 6.4 (at least needs testing) attributes must be aligned with the corresponding property attributes (
QTBUG-105708) - ☒ aliases to private properties
- ☒ (at least needs extra testing) aliases to group properties (and properties inside group/attached property):
broken: Text's font.letterSpacing cannot be aliases at the moment
- ☒ extension types (like font, etc.) must be preferred over real types
- ☒ default aliases (fixed along the way in
QTBUG-105708)
- ☒ Enums
- mapped to C++ enumerations
- require special code to be accessible in JavaScript (Q_ENUMS should be enough for the meta-object system)
- ☒ Signals
- mapped to C++ signals and marked as Q_SIGNALS
- ☒ Methods/functions
- call JavaScript code through QQmlEnginePrivate::executeRuntimeFunction()
- marked as Q_INVOKABLE
special attribute: default method(deprecated in I001ddf4d7933871977f84a5e012d020fb043cc6)
- ☐ Inline components (
QTBUG-105946)- terra incognita
- they define a new type (as if having a separate QML file), so must be handled similarly (extra care should be given to how context hierarchy is handled for them: as for document roots?)
- they use the compilation unit of the QML file (no separate CU)
- they support cyclic references but not cyclic instantiations (would it actually work for qmltc? might have to use QQmlComponent wrapping just because of this)
import QtQuick 2.15 Item { component A : Item { property B b // NB: if "b: B {}", it should be a recursion error } component B : Item { property A a } A { b: B { Component.onCompleted: console.log(a) } } }
-
- could be troublesome in the code resolving names to types (e.g. is Foo.Bar an enum.enumerator or an inline component?)
- Bindings
- ☒ Invalid (noop for compiler)
- Property value assignments
- ☒ Boolean, Number
- ☒ String
- ☒ Null
- ☐ (in general) support conversions between types; complex cases use QQmlStringConverters (TODO: think whether this is actually in scope of qmltc or in scope of qmlsc/qmlcachegen)
- ☐ (in general) must follow QQmlObjectCreator::setPropertyValue() logic
- ☐ (at least requires more tests?) (in general) must be aware of type conversions (e.g. bool -> int, int -> bool, etc.)
- ☒ Translations (see
QTBUG-104637)- QV4::CompiledData::Binding::Type_Translation
- QV4::CompiledData::Binding::Type_TranslationById
- terra incognita (not addressed at all currently)
- ☒ Generic script bindings on a property
- call JavaScript code through QQmlEnginePrivate::executeRuntimeFunction()
- can be bound to both old style and new style properties (notify and bindable respectively)
-
- ☒ Signal handlers (similar to methods). TODO: there are issues e.g.
QTBUG-99317- call JavaScript code through QQmlEnginePrivate::executeRuntimeFunction()
- marked as Q_SLOT
- connected to signals (TODO: we might prefer using
- ☒ Property change handlers
- call JavaScript code through QQmlEnginePrivate::executeRuntimeFunction()
- can be "attached" to both old style and new style properties (notify and bindable respectively)
- can be "attached" to properties of different kinds (private, group, attached, list( ? ))
- ☒ Object bindings
- implement type hierarchy
- ☒ Bindings on attached properties
- aggregate bindings for individual attached properties, then recurse to bindings of other types
- in a nutshell, `this->setBinding` is changed into `this->prop->setBinding`
- ☒ Bindings on group properties
- aggregate bindings for individual group properties, then recurse to bindings of other types
- in a nutshell, `this->setBinding` is changed into `this->prop->setBinding`
- extra care with value types needed (well-defined semantics has to be specified yet: what happens on write if there's a connection, binding, etc.)
- ☒ Bindings with regular expressions
- See QQmlJSImportVisitor::parseLiteralBinding() for literal regular expressions
- Non-literal ones can probably be handled as script bindings
- ☐ Intriguing bindings (with more cases in QtDS examples e.g. coffee machine)
RangeSlider { first.handle.objectName: "rangeslider.first" second.handle.objectName: "rangeslider.second" }
import QtQuick 2.15 import QtQuick.Window 2.15 Window { id: window width: 600 height: 600 visible: true Image { id: sequence } property alias sequence: sequence sequence.layer.enabled: false // QTBUG-94983 but the syntax is still valid? }
- ☒ Signal handlers (similar to methods). TODO: there are issues e.g.
-
- ☒ Bindings on types with extensions (literal ones mostly):
- We should acquire the extenstion type from the real one and use extenstion type's READ/WRITE/etc (if a method exists). There are cases (`font.letterSpacing: 42`) which would likely fail to work otherwise.
- ☒ Bindings on types with extensions (literal ones mostly):
- ☐ Singleton objects
- haven't looked at it much, should require special code generation but nothing to redesign in the compiler/codegen (hopefully)
- could both come from QML (related to Pragma) or C++
- ☐ Pragmas
- Singleton: handled via qmldir
- Strict: unclear if this one needs to be supported
- ☐ (at least requires testing; mostly relies on qmlcompiler lib?) Namespaces
- ☒ QML "namespaces" (related mostly to how QML modules are imported)
- C++ namespaces (a C++ type exposed to QML could be declared inside a namespace; that namespace should be visible and usable by the compiler)
- Special cases
- ☒ 6.4 (basic support exists, might need QQmlObjectCreator-aligned model however) Component.onCompleted and Component.onDestruction - https://codereview.qt-project.org/c/qt/qtdeclarative/+/419466
- ☒ Component-wrapped types (require QQmlComponent wrapping in the generated code)
- ☐ (at least needs testing) C++ singletons (might require some boilerplate)
- ☒ "on" assignments (do not seem to semantically differ from normal binding constructions)
`parent` property(appear only inside bindings/JS code/etc.)
QML importing related:
- ☐ (at least needs testing) JavaScript resources support
- One example: JavaScript imports (context->setImportedScripts)
- ☒ Local importing of QML types (compiled within the same binary; related to
QTBUG-95598) - ☐ Plugin interaction
- Unclear if should be explicitly rejected: if there's a qmldir/qmltypes, the type compiler might actually be able to process the QML types that are plugin-provided (but the generated code is useless)
- ☒ (covered by qmlcompiler lib) Module imports with/without qualifiers/namespaces
- could require special instructions for the engine to ensure the qualifiers/namespaces are registered in JavaScript
QQmlEngine/runtime and QtQuick related:
- ☐ (basic support exists, needs URL resolution tests) QQmlContext hierarchy for created types (influences JavaScript lookups - e.g. id, inherited methods)
- There's also a notion of scope
- URL resolution is affected by the hierarchy (see https://codereview.qt-project.org/c/qt/qtdeclarative/+/369994 for interesting test cases)
- the to-be-introduced operator '@' must behave identically to the QQmlComponent-originated objects, same applies to Qt.resolvedUrl()
- ☒ Q_INTERFACES (note that these interfaces are inherited, so each subclass' instance should call the interface methods):
- QQmlParserStatus (QQuickAnimationController)
- QQmlPropertyValueInterceptor [4] (QQuickBehavior)
- QQmlPropertyValueSource [5] (QQuickAbstractAnimation)
- QQmlFinalizerHook
- ☐ Image providers
- terra incognita (no additional code is generated at the moment)
- QQmlObjectCreator::sharedState (has to be available when creating generated types)
QQmlObjectCreator::sharedState>finalizeCallbacks (implicitly related to QQmlParserStatus)- – replaced by QQmlFinalizerHook (once available)- ☐ (at least needs use case + tests) QQmlObjectCreator::sharedState->allJavaScriptObjects (unclear whether these are needed)
- ☒ QQmlObjectCreator::sharedState->componentAttached (related to Component.onCompleted/onDestruction; unclear whether needed)
- Deferred bindings (terra incognita; a.k.a. deferred properties?)
- ☐ Custom parser types (need to figure whether these should be supported at all -
QTBUG-95117)- (in general) must be rejected in favor of generalized group properties (which are yet to be supported)
- QQmlListModel (QML ListModel)
- QQmlConnections (QML Connections)
- QQuickPropertyChanges (QML PropertyChanges)
- SignalTransition
- QtQuick concepts
- Visual parents
- States
- Transitions
- Animations (related to Q_INTERFACES(QQmlPropertyValueSource))
- Animators
- Animated sprites
- ☐ (at least needs testing/use case) Resource loading (local, network, etc.)
- (in general) might require certain network-related code to be generated (e.g. if there's smth handled by QQmlObjectCreator)
- terra incognita
- ☐ Extra QML_ macros (at least needs testing):
- ☒ QML_EXTENDED, QML_EXTENDED_NAMESPACE
- ☐ QML_FOREIGN_NAMESPACE
- related to QML language elements, ideally should not require any additional work
- ☒ (https://codereview.qt-project.org/c/qt/qtdeclarative/+/382086) Object finalization order is as follows:
- 1) QQmlParserStatus objects are finalized (via componentComplete())
- 2) QQmlFinalizerHook objects are finalized (via componentFinalized())
- 3) Component.onComplete attached signals are finalized (in qqmlobjectcreator.cpp via `emit obj->complete()`)
- (in general) qmltc must ensure this order is preserved. note: within-step order of componentComplete()/componentFinalized()/Component.onCompleted is undefined (so root's componentComplete() might happen before some child's componentComplete()).
- (in general) simplest solution is to allow componentComplete() to run as part of normal object creation, then generate hardcoded instructions for componentFinalized() [as those are somewhat rare] and Component.onComplete():
void DocumentRoot::finalize() { // assume at this point that all componentComplete() are run // QQmlFinalizerHooks: ((QQmlFinalizerHooks *)this->getRandomChild()->getRandomChild())->componentFinalized(); // ... // Component.onCompleted: // ... }
- ☐ Elements with unclear usage / support model:
- QQmlIncubationController
- QQmlAbstractUrlInterceptor
- QQmlInstantiationInterrupt
- QML State (related to PropertyChanges; might require special code generation?)
Codegen features (not related to the language/runtime but nice-to-haves for the compilation):
- ☒ Generate namespace for the classes (to avoid name collisions)
- Might be optional (with a --namespace argument for qmltc) or "always on"
- ☐ 6.4 Generate export macro and use that for each generated type (related to QTBUG-96040)
—
(Poorly formatted) comments:
- Interceptors [4] and property value sources [5] (also test how group/attached properties behave with property value sources) – some very basic support added but more work required
- Proper QQmlEngine context hierarchy – done; fairly extensive tests exist (NB: new hierarchy is not identical to what QQmlComponent generates but this is intentional)
- Property aliases – partially done; but: need to ensure aliases mimic all Q_PROPERTY attributes of the origins (as much as type inference allows). one missing feature is RESET support.
- List properties (and list types?) in various shapes and forms (do we need to handle QQmlJSScope::AccessSemantics::Sequence in any interesting ways?) – partially done for list properties (e.g. object bindings) but it's unclear if there's more depth in it
- Delegates (apparently the parent of a delegate could be a fairly random thing? e.g. contentItem in ListView): must be correctly constructed despite the shenanigans
- QQmlComponent-based types (usually handled in a special way by loading the component at runtime through QQmlComponent::create()) – delegates are handled but the rest isn't
[1]: https://doc.qt.io/qt-6/qtqml-syntax-basics.html
[2]: https://doc.qt.io/qt-6/qtqml-documents-topic.html
[3]: https://doc.qt.io/qt-6/qmlbasictypes.html and https://doc.qt.io/qt-6/qtqml-typesystem-basictypes.html
[4]: https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html#property-modifier-types
[5]: https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html#property-value-sources
—
Other useful links:
https://doc.qt.io/qt-6/qmlreference.html
Attachments
Issue Links
- depends on
-
QTBUG-104637 Support translation bindings in qmltc
- Closed
-
QTBUG-104638 Support RegExpLiteral bindings in qmltc
- Closed
-
QTBUG-105378 qmltc: generalized group properties
- Closed
-
QTBUG-105708 qmltc: test alias on property with attributes
- Closed
-
QTBUG-105946 qmltc: inline components
- Closed
- is replaced by
-
QTBUG-105538 qmltc evolution collection task
- Open
- relates to
-
QTBUG-105538 qmltc evolution collection task
- Open
-
QTBUG-96041 Support language/engine features sufficient for the prototype
- Closed
For Gerrit Dashboard: QTBUG-91956 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
361755,4 | Prototype private property access in tst_qmltc_manual | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
402521,3 | Separate script bindings from others in generated qmltc code | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
408027,26 | Address extension types in qmltc | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
418271,6 | qmltc: Ensure properties with MEMBER can be read and written | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
419446,5 | qmltc: Support CONSTANT and RESET property attributes in aliases | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
419466,3 | qmltc: Make Component.onCompleted compilation less special | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
419781,2 | qmltc: Ensure properties with MEMBER can be read and written | 6.4 | qt/qtdeclarative | Status: MERGED | +2 | 0 |
421118,2 | qmltc: Make Component.onCompleted compilation less special | 6.4 | qt/qtdeclarative | Status: MERGED | +2 | 0 |
423536,3 | qmltc: Acknowledge BINDABLE-only properties | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
423773,5 | Support RegExpLiteral bindings in qmltc | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |
423939,4 | Support RegExpLiteral bindings in qmltc | 6.4 | qt/qtdeclarative | Status: MERGED | +2 | 0 |
424116,2 | qmltc: Acknowledge BINDABLE-only properties | 6.4 | qt/qtdeclarative | Status: ABANDONED | +2 | 0 |
424237,3 | Separate script bindings from others in generated qmltc code | 6.4 | qt/qtdeclarative | Status: MERGED | +2 | 0 |