We can resolve lookups for objects referenced by id at QML compile time
and use a run-time helper to extract the id object out of the QML context
data by index instead of name.
Dependencies to id objects are also tracked at compile time and registered
separately before entering the generated function code.
The lookup of id objects is encoded in the IR as special member lookups.
Members will also then in the future be used to for property lookups in context
and scope properties, as well as any other property lookups in QObjects where
we can determine the meta-object.
Change-Id: I36cf3ceb11b51a983da6cad5b61c3bf574acc20a
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Implements QQmlCodeGenerator::visit(AST::UiPragma *) to process any
pragma statements in a QML file for the new V4 compiler approach.
Only pragma Singleton is supported, others will generate errors.
Also adds necessary hooks to treat types as Singletons. Basic
functionality is working, but three of the QML Singleton unit tests
fail. Some of them are dependent on other language capabilities that
seem to have problems.
In addition removes unnecessary toString() call in the equivalent
visit(AST::UiPragma *) function of the old parser.
Change-Id: Iec9fa887f953b80b7f9a11878d846637a8f519ef
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
With a growing number of functions per module, these calls become
expensive and are unnecessary. defineFunction in the code generator
can simply return the correct index right away.
Change-Id: I8ab56a3083bf215674a1b46c502b415be694e465
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This is done by re-using the JS code generator from the new compiler. A few bugs were
fixed on the way:
* The index into the compiledData->runtimeFunctions array is not the same as the function
index when they are collected (from the AST), as for example binding expressions may create
extra V4IR::Function objects that break the 1:1 mapping. Therefore the JS code gen will return
a mapping from incoming function index to V4IR::Module::Function (and thus runtimeFunction)
* Binding expressions in the old backend get usually unpacked from their ExpressionStatement node.
The reference to that node is lost, and instead of trying to preserve it, we simply synthesize it
again. This won't be necessary anymore with the new compiler in the future.
* Commit 1c29d63d60 ensured to always look up locals by name, and so
we have to do the same when initializing the closures of nested functions inside binding expressions
(in qv4codegen.cpp)
* Had to change the Qml debugger service auto-test, which does toString() on a function that is now compiled.
Even if we implemented FunctionPrototype::toString() to do what v8 does by extracting the string from the
file, it wouldn't help in this test, because it feeds the input from a string instead of a file.
* In tst_parserstress we now end up compiling all JS code, which previously was only parsed. This triggers
some bugs in the SSA handling. Those tests are skipped and tracked in QTBUG-34047
Change-Id: I44df51085510da0fd3d99eb5f1c7d4d17bcffdcf
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
In order to determine the type of lookup we need (name or directly in
environment members), we used Codegen::_mode, which is set to the currently
suitable mode depending on the function (parameter to defineFunction). However
that's not quite correct, the look-up mode depends on the function itself, not
where it was called from. This patch corrects that by moving the compilation
mode into the Environment itself.
This is needed by follow-up patches.
Additionally the "bool deletable" parameter to the builtin_declare_vars was
always set to false, because it used mode instead of _mode, which was never set
to Eval or QmlBinding. This will be cleaned up in a future patch.
Change-Id: I878f187945e5de091689ab5d70a0f33eb5a9e38f
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Saves up on memory allocations.
Change-Id: I0f7c82521b0b10085861fc62fed9b9d591169b5a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Match exactly the VME code path by reporting the right type of error
as well as the right hand side of the alias binding if necessary.
Change-Id: I35d192a20641e0acbf25d20f3dc5fb53cc7cbae5
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
It may happen that people forget the colon after the handler name in
onSomeSignal { code here }
and we have to print out the correct error message. It looks like a
group property, but we can identify this binding due to its reserved
use of starting with "on".
Change-Id: I7c502c1a2a5f2a6c613879468a60bc57a7d20fe8
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Introduce a simple valdator pass early on to catch those assignments. Also
fix storing the correct line/col for default property object bindings and
remember the minor/major version of an import in the final type reference.
Change-Id: Ib2a93dfe1a30fcd9c09b5443fb8199ad11b19769
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Grab the line/column from the import token, not the import id token,
as the latter is not always present in all import statements.
Change-Id: Iaa0c2f1d60422fb779fa7a6c4fd1c895fa3f777b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This introduces Singleton support for QML (Composite Singleton). For
now, the Singleton support is only availabe for QML types in modules
or (remote and local) directories with qmldir file. However, in the
future this support may be expanded to arbitrary QML file imports
without by leaving out the qmldir requirement.
You define a QML type as a Singleton with the following two steps:
1. By adding a pragma Singleton to a type's QML file:
pragma Singleton
The pragma and import statements can be mixed and their order does
not matter. Singleton is the only supported pragma for now. Others
will generate errors.
2. By specifying a qmldir file for the directory of your imported
type and prepending the type with "singleton" keyword as follows:
singleton TestTypeSingleton TestTypeSingleton.qml
Alternatively you may specify a qmldir file for a module and specify
your type as a singleton as follows:
singleton TestTypeSingleton 1.0 TestTypeSingleton.qml
Composite Singletons may be included in a module and may be used with
a local namespace qualifier when imported with:
"import xxx as NameSpace"
A singleton instance is created at first use and stored into the
QmlEngine (one instance per engine) and eventually released by the
engine's destructor.
CompositeSingletonType has a dual nature and will return true to both
isComposite() and isSingleton() calls. In most cases its enough to
check for just isComposite() or isSingleton(). However, there is a
isCompositeSingleton() available as well.
I used "qlalr --no-debug --no-lines --qt qqmljs.g" to generate the
qqmljsparser and qqmljsgrammar files from qqmljs.g.
Unit tests are included.
Change-Id: I91b303612c5e132143b325b9a8f982e9355bc90e
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
When compiling signal handler expressions we need to determine the parameters.
We first try to look up the signal in the base meta-object. For our own
QML type itself we don't have a meta-object yet and so we extract the information
about which parameters the signals have from the parsed AST's signal declarations.
For signal handlers on declared properties we need to "synthesize" the
signal (myPropertyChanged) as well, with an empty parameter list.
Change-Id: Iecfe7bc7a9979d57586cbd9434bb9eb2f38a2c7b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Aliases are resolved at "compile time", not rough JS expressions. This is
done right after we determined the scope of components in the QML file,
which is also where we collect object ids (that aliases use).
Change-Id: If5702337f2cca08d17f196c3b2fde3bbdfea5b3c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Produce an error message as expected by auto-tests.
Change-Id: I28caf2ac20692e2e3b055a61289bb02372047a65
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Change defineFunction back to taking AST::SourceElements for the body (how it
was originally)
Then in the new compiler, do the same "function->body ? function->body->elements
: 0" dance for function expressions and for binding expressions, synthesize the
AST::SourceElements.
Change-Id: Iaedb15925a6bb8482cde2b371a6e781477252435
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
We use a dedicated pass through the objects in QV4::CompiledData::QmlUnit to determine
which objects are QQmlComponents. We remember their object indices as well as to which
component other objects belong to (if any).
Change-Id: I97929c57e2ccb2fd380d612002d128359c4bc253
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Disallow properties called id.foo.bar as well as id: Object {}
Change-Id: I3e31875a5863b5b4d4f9f7dd6c74d337eea3dfb2
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
id: foo;
produces a statement on the right hand side that includes the semicolon.
Strip it off - reduce expression statements similar to setBindingValue.
Change-Id: I22a02ce364a309b4364476166402f8284e01ef98
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Make sure to call defineFunction with FunctionCode as compile mode when
compiling functions or signal handler functions, to assign an index to local
variables.
Change-Id: I8948840dba68ce6293a87c55d3386df69d5f6a5c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Setting a value on a list property is always just appending to the list instead
of replacing it. Based on that, initializing list properties with multiple
items is done with one binding per item to the same list property. So
myList: [ Item{}, Item{} ]
is mapped to
myList: Item {}
myList: Item {}
Change-Id: Iadc048ab3a8d73ac824aa6b2ae5dec33731fa362
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Determine when a qualified identifier signifies an attached property or a group
property in one place and set the Binding::Type accordingly.
This simplifies the object builder code, too.
Change-Id: I9f572441e9b5b43338752b848649fbd507cabe4c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Attached properties are implemented similarly to group properties, except that
the object operated on isn't a QQmlValueType from a property (i.e. font) but the
QObject that implements the attached properties.
Change-Id: If73751162c191c65512ca1bddadd6270e6e33793
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Signal handlers start out in the parser as binding expressions. A new
SignalHandlerConverter converts the bindings then so that the expression is
turned into a function declaration where the function parameters match the
parameters of the signal.
Change-Id: I3ea5aa3b80a6ee3b095c6841c63c3e3bb0b47e4f
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
For example when declaring
signal mySignal(string blah)
then we don't need to try to "resolve" the type "string".
Change-Id: I80924ebf244c6b8e2827d19f9c78faf93031fe15
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Binding expressions and QML used to be set up so that they were written
as function closure:
(function(...) {
expression here
})
and then evaluated inside qml scope. With the new setup we do that closure
setup manually now.
For that we have to define a dummy outter "context scope" function in the
codegen, that will later be used to look up the context ids.
Change-Id: I0656419d67a1728451fcd46f402b03979f118b0b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This implements support for "font.pixelSize: 24" for example. The representation
in the compile data structure is so that font.pixelSize is short-hand for
font {
pixelSize: 24
}
which means that inside the braces is a complete object initializer. For that
initializer we create a dedicated CompiledData::Object, which however has its
type name empty. When populating the outer instance then, the "font" property
is read as QQmlValueType (a QObject) and instead of creating a new QObject we
use that value type as instance to run the rest of the QML object initializer
(everything in braces).
Change-Id: Ic0a37ac77ab88f582546b9c09a3d06a07726420b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Collect all references to unknown types after parsing, re-use the existing code
in QQmlTypeLoader to resolve them and finally use the resolved references map
in the QQmlObjectCreator instead of the type name cache directly.
Change-Id: I8b83af4f8852e79c33985457081c024358bb9622
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Re-enable COMPILE_EXCEPTION calls that were commented out due to missing
location information (that this patch also adds).
Change-Id: I0d584f474cc7e879350c8aae2869a9603ba415aa
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Errors for example in signal declarations are usually reported in the loader
thread, during property cache construction. This patch separates out the
property cache population into QQmlPropertyCacheCreator, runs it from the
loader thread and reduces the QQmlObjectCreator to merely set the properties/bindings/
functions on the object.
This also enables location tracking for signal declarations and their error reporting.
Change-Id: Ief1ffbb3113f8279a50d1a12dab8dbe096702a60
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Record the line/column in the signal and report it together with the url
if there was an error in declaring the signals.
Change-Id: Idbbee9be271b0ca55709ffc1791637595d7ebd89
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
The goal is to parse QML and JavaScript binding expressions/functions in one
go and generate data structures that allow for the parsing to happen in a thread
and the instantiation of the object tree in another thread, just reading from
the generated data structures. This will replace qqmlcompiler and the VME.
This new way of loading QML is currently hidden behind the QML_NEW_COMPILER=1
environment variable. There's lots of work left to fill in the gaps in object
construction, Component support, Component.onComplete, error messages, etc. etc.
Change-Id: I5e40643cff169f469f0b6ce151584ffee5ca5e90
Reviewed-by: Lars Knoll <lars.knoll@digia.com>