1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #ifndef QQMLCOMPILER_P_H
43 #define QQMLCOMPILER_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
57 #include "qqmlerror.h"
58 #include <private/qv8_p.h>
59 #include "qqmlinstruction_p.h"
60 #include "qqmlscript_p.h"
61 #include "qqmlengine_p.h"
62 #include <private/qbitfield_p.h>
63 #include "qqmlpropertycache_p.h"
64 #include "qqmlintegercache_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmltypeloader_p.h"
68 #include <QtCore/qbytearray.h>
69 #include <QtCore/qset.h>
70 #include <QtCore/QCoreApplication>
77 class QQmlContextData;
79 class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
82 QQmlCompiledData(QQmlEngine *engine);
83 virtual ~QQmlCompiledData();
89 QQmlTypeNameCache *importCache;
93 bool isRegisteredWithEngine;
98 : type(0), typePropertyCache(0), component(0) {}
101 QQmlPropertyCache *typePropertyCache;
102 QQmlCompiledData *component;
104 QQmlPropertyCache *propertyCache() const;
105 QQmlPropertyCache *createPropertyCache(QQmlEngine *);
107 QList<TypeReference> types;
110 V8Program(const QByteArray &p, QQmlCompiledData *c)
111 : program(p), cdata(c) {}
114 v8::Persistent<v8::Array> bindings;
115 QQmlCompiledData *cdata;
118 QList<V8Program> programs;
120 QQmlPropertyCache *rootPropertyCache;
121 QList<QString> primitives;
122 QList<QByteArray> datas;
124 QList<QQmlPropertyCache *> propertyCaches;
125 QList<QQmlIntegerCache *> contextCaches;
126 QList<QQmlScriptData *> scripts;
130 #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
131 FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
132 #undef QML_INSTR_DATA_TYPEDEF
137 void dumpInstructions();
140 int addInstruction(const QQmlInstructionData<Instr> &data)
142 QQmlInstruction genericInstr;
143 QQmlInstructionMeta<Instr>::setData(genericInstr, data);
144 return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
146 int nextInstructionIndex();
147 QQmlInstruction *instruction(int index);
148 QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
150 bool isInitialized() const { return hasEngine(); }
151 void initialize(QQmlEngine *);
154 virtual void destroy(); // From QQmlRefCount
155 virtual void clear(); // From QQmlCleanup
158 friend class QQmlCompiler;
160 int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
161 void dump(QQmlInstruction *, int idx = -1);
162 QQmlCompiledData(const QQmlCompiledData &other);
163 QQmlCompiledData &operator=(const QQmlCompiledData &other);
165 int indexForString(const QString &);
166 int indexForByteArray(const QByteArray &);
167 int indexForUrl(const QUrl &);
170 namespace QQmlCompilerTypes {
171 struct BindingContext
174 : stack(0), owner(0), object(0) {}
175 BindingContext(QQmlScript::Object *o)
176 : stack(0), owner(0), object(o) {}
177 BindingContext incr() const {
178 BindingContext rv(object);
179 rv.stack = stack + 1;
182 bool isSubContext() const { return stack != 0; }
185 QQmlScript::Object *object;
188 struct BindingReference
190 enum DataType { QtScript, V4, V8,
195 struct JSBindingReference : public QQmlPool::Class,
196 public BindingReference
198 JSBindingReference() : isSafe(false), nextReference(0) {}
200 QQmlScript::Variant expression;
201 QQmlScript::Property *property;
202 QQmlScript::Value *value;
204 int compiledIndex:15;
208 QString rewrittenExpression;
209 BindingContext bindingContext;
211 JSBindingReference *nextReference;
214 struct TrBindingReference : public QQmlPool::POD,
215 public BindingReference
222 struct IdList : public QFieldList<QQmlScript::Object,
223 &QQmlScript::Object::nextIdObject>
225 QQmlScript::Object *value(const QString &id) const {
226 for (QQmlScript::Object *o = first(); o; o = next(o)) {
235 DepthStack() : _depth(0), _maxDepth(0) {}
236 DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
237 DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
239 int depth() const { return _depth; }
240 int maxDepth() const { return _maxDepth; }
242 void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
243 void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
245 void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
251 // Contains all the incremental compiler state about a component. As
252 // a single QML file can have multiple components defined, there may be
253 // more than one of these for each compile
254 struct ComponentCompileState : public QQmlPool::Class
256 ComponentCompileState()
257 : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
258 v8BindingProgramLine(-1), root(0) {}
261 int parserStatusCount;
262 int totalBindingsCount;
263 int pushedProperties;
266 QByteArray compiledBindingData;
267 QByteArray v8BindingProgram;
268 int v8BindingProgramLine;
270 DepthStack objectDepth;
271 DepthStack listDepth;
273 typedef QQmlCompilerTypes::JSBindingReference B;
274 typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
275 JSBindingReferenceList bindings;
276 typedef QQmlScript::Object O;
277 typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
278 AliasingObjectsList aliasingObjects;
279 QQmlScript::Object *root;
283 class QMetaObjectBuilder;
284 class Q_AUTOTEST_EXPORT QQmlCompiler
286 Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
288 QQmlCompiler(QQmlPool *);
290 bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
292 bool isError() const;
293 QList<QQmlError> errors() const;
295 static bool isAttachedPropertyName(const QString &);
296 static bool isSignalPropertyName(const QString &);
297 static bool isAttachedPropertyName(const QHashedStringRef &);
298 static bool isSignalPropertyName(const QHashedStringRef &);
300 int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
301 const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
302 int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
303 QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler
306 typedef QQmlCompiledData::Instruction Instruction;
308 static void reset(QQmlCompiledData *);
310 void compileTree(QQmlScript::Object *tree);
313 bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
314 bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
315 bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
316 bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
317 const QQmlCompilerTypes::BindingContext &);
318 bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
319 const QQmlCompilerTypes::BindingContext &);
320 bool buildPropertyInNamespace(QQmlImportNamespace *ns,
321 QQmlScript::Property *prop,
322 QQmlScript::Object *obj,
323 const QQmlCompilerTypes::BindingContext &);
324 bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
325 bool buildAttachedProperty(QQmlScript::Property *prop,
326 QQmlScript::Object *obj,
327 const QQmlCompilerTypes::BindingContext &ctxt);
328 bool buildGroupedProperty(QQmlScript::Property *prop,
329 QQmlScript::Object *obj,
330 const QQmlCompilerTypes::BindingContext &ctxt);
331 bool buildValueTypeProperty(QObject *type,
332 QQmlScript::Object *obj,
333 QQmlScript::Object *baseObj,
334 const QQmlCompilerTypes::BindingContext &ctxt);
335 bool buildListProperty(QQmlScript::Property *prop,
336 QQmlScript::Object *obj,
337 const QQmlCompilerTypes::BindingContext &ctxt);
338 bool buildScriptStringProperty(QQmlScript::Property *prop,
339 QQmlScript::Object *obj,
340 const QQmlCompilerTypes::BindingContext &ctxt);
341 bool buildPropertyAssignment(QQmlScript::Property *prop,
342 QQmlScript::Object *obj,
343 const QQmlCompilerTypes::BindingContext &ctxt);
344 bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
345 QQmlScript::Object *obj,
346 QQmlScript::Value *value,
347 const QQmlCompilerTypes::BindingContext &ctxt);
348 bool buildPropertyOnAssignment(QQmlScript::Property *prop,
349 QQmlScript::Object *obj,
350 QQmlScript::Object *baseObj,
351 QQmlScript::Value *value,
352 const QQmlCompilerTypes::BindingContext &ctxt);
353 bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
354 QQmlScript::Object *obj,
355 QQmlScript::Value *value,
356 const QQmlCompilerTypes::BindingContext &ctxt);
357 bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
358 bool testLiteralAssignment(QQmlScript::Property *prop,
359 QQmlScript::Value *value);
360 bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
361 QQmlScript::Object *obj,
362 QQmlScript::Value *value,
364 enum DynamicMetaMode { Normal, ForceCreation };
365 bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
366 bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
367 bool buildDynamicMetaAliases(QQmlScript::Object *obj);
368 bool checkDynamicMeta(QQmlScript::Object *obj);
369 bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
370 const QQmlCompilerTypes::BindingContext &ctxt);
371 bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
372 const QQmlCompilerTypes::BindingContext &ctxt);
373 bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
374 bool completeComponentBuild();
375 bool checkValidId(QQmlScript::Value *, const QString &);
378 void genObject(QQmlScript::Object *obj, bool parentToSuper = false);
379 void genObjectBody(QQmlScript::Object *obj);
380 void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
381 void genComponent(QQmlScript::Object *obj);
382 void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
383 void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
384 void genPropertyAssignment(QQmlScript::Property *prop,
385 QQmlScript::Object *obj,
386 QQmlScript::Property *valueTypeProperty = 0);
387 void genLiteralAssignment(QQmlScript::Property *prop,
388 QQmlScript::Value *value);
389 void genBindingAssignment(QQmlScript::Value *binding,
390 QQmlScript::Property *prop,
391 QQmlScript::Object *obj,
392 QQmlScript::Property *valueTypeProperty = 0);
393 int genContextCache();
395 QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
396 QQmlScript::Property *valueTypeProp);
398 int componentTypeRef();
399 int translationContextIndex();
401 QQmlType *toQmlType(QQmlScript::Object *from);
402 bool canCoerce(int to, QQmlScript::Object *from);
404 QString elementName(QQmlScript::Object *);
406 QStringList deferredProperties(QQmlScript::Object *);
408 QQmlPropertyCache *propertyCacheForObject(QQmlScript::Object *);
409 QQmlPropertyData *property(QQmlScript::Object *, int);
410 QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
411 bool *notInRevision = 0);
412 QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
413 bool *notInRevision = 0);
414 int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
415 int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
416 int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
418 void addId(const QString &, QQmlScript::Object *);
422 void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
424 QQmlCompilerTypes::ComponentCompileState *compileState;
428 QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
429 void saveComponentState();
431 QList<QQmlError> exceptions;
432 QQmlCompiledData *output;
434 QQmlEnginePrivate *enginePrivate;
435 QQmlScript::Object *unitRoot;
437 int cachedComponentTypeRef;
438 int cachedTranslationContextIndex;
440 // Compiler component statistics. Only collected if QML_COMPILER_STATS=1
443 ComponentStat() : lineNumber(0), ids(0), objects(0) {}
448 QList<QQmlScript::LocationSpan> scriptBindings;
449 QList<QQmlScript::LocationSpan> sharedBindings;
450 QList<QQmlScript::LocationSpan> optimizedBindings;
453 struct ComponentStats : public QQmlPool::Class
455 ComponentStat componentStat;
456 QList<ComponentStat> savedComponentStats;
458 ComponentStats *componentStats;
463 #endif // QQMLCOMPILER_P_H