1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
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,
83 QQmlCompiledData(QQmlEngine *engine);
84 virtual ~QQmlCompiledData();
90 QQmlTypeNameCache *importCache;
95 : type(0), typePropertyCache(0), component(0) {}
99 QQmlPropertyCache *typePropertyCache;
100 QQmlCompiledData *component;
102 const QMetaObject *metaObject() const;
103 QQmlPropertyCache *propertyCache() const;
104 QQmlPropertyCache *createPropertyCache(QQmlEngine *);
106 QList<TypeReference> types;
109 V8Program(const QByteArray &p, QQmlCompiledData *c)
110 : program(p), cdata(c) {}
113 v8::Persistent<v8::Array> bindings;
114 QQmlCompiledData *cdata;
117 QList<V8Program> programs;
119 const QMetaObject *root;
120 QAbstractDynamicMetaObject rootData;
121 QQmlPropertyCache *rootPropertyCache;
122 QList<QString> primitives;
123 QList<QByteArray> datas;
125 QList<QQmlPropertyCache *> propertyCaches;
126 QList<QQmlIntegerCache *> contextCaches;
127 QList<QQmlScriptData *> scripts;
131 #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
132 FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
133 #undef QML_INSTR_DATA_TYPEDEF
138 void dumpInstructions();
141 int addInstruction(const QQmlInstructionData<Instr> &data)
143 QQmlInstruction genericInstr;
144 QQmlInstructionMeta<Instr>::setData(genericInstr, data);
145 return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
147 int nextInstructionIndex();
148 QQmlInstruction *instruction(int index);
149 QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
151 bool isInitialized() const { return hasEngine(); }
152 void initialize(QQmlEngine *);
155 virtual void destroy(); // From QQmlRefCount
156 virtual void clear(); // From QQmlCleanup
159 friend class QQmlCompiler;
161 int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
162 void dump(QQmlInstruction *, int idx = -1);
163 QQmlCompiledData(const QQmlCompiledData &other);
164 QQmlCompiledData &operator=(const QQmlCompiledData &other);
166 int pack(const char *, size_t);
168 int indexForString(const QString &);
169 int indexForByteArray(const QByteArray &);
170 int indexForUrl(const QUrl &);
173 namespace QQmlCompilerTypes {
174 struct BindingContext
177 : stack(0), owner(0), object(0) {}
178 BindingContext(QQmlScript::Object *o)
179 : stack(0), owner(0), object(o) {}
180 BindingContext incr() const {
181 BindingContext rv(object);
182 rv.stack = stack + 1;
185 bool isSubContext() const { return stack != 0; }
188 QQmlScript::Object *object;
191 struct BindingReference
193 enum DataType { QtScript, V4, V8,
198 struct JSBindingReference : public QQmlPool::Class,
199 public BindingReference
201 JSBindingReference() : nextReference(0) {}
203 QQmlScript::Variant expression;
204 QQmlScript::Property *property;
205 QQmlScript::Value *value;
209 QString rewrittenExpression;
210 BindingContext bindingContext;
212 JSBindingReference *nextReference;
215 struct TrBindingReference : public QQmlPool::POD,
216 public BindingReference
223 struct IdList : public QFieldList<QQmlScript::Object,
224 &QQmlScript::Object::nextIdObject>
226 QQmlScript::Object *value(const QString &id) const {
227 for (QQmlScript::Object *o = first(); o; o = next(o)) {
236 DepthStack() : _depth(0), _maxDepth(0) {}
237 DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
238 DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
240 int depth() const { return _depth; }
241 int maxDepth() const { return _maxDepth; }
243 void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
244 void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
246 void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
252 // Contains all the incremental compiler state about a component. As
253 // a single QML file can have multiple components defined, there may be
254 // more than one of these for each compile
255 struct ComponentCompileState : public QQmlPool::Class
257 ComponentCompileState()
258 : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
259 v8BindingProgramLine(-1), root(0) {}
262 int parserStatusCount;
263 int totalBindingsCount;
264 int pushedProperties;
267 QByteArray compiledBindingData;
268 QByteArray v8BindingProgram;
269 int v8BindingProgramLine;
271 DepthStack objectDepth;
272 DepthStack listDepth;
274 typedef QQmlCompilerTypes::JSBindingReference B;
275 typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
276 JSBindingReferenceList bindings;
277 typedef QQmlScript::Object O;
278 typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
279 AliasingObjectsList aliasingObjects;
280 QQmlScript::Object *root;
284 class QMetaObjectBuilder;
285 class Q_AUTOTEST_EXPORT QQmlCompiler
287 Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
289 QQmlCompiler(QQmlPool *);
291 bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
293 bool isError() const;
294 QList<QQmlError> errors() const;
296 static bool isAttachedPropertyName(const QString &);
297 static bool isSignalPropertyName(const QString &);
298 static bool isAttachedPropertyName(const QHashedStringRef &);
299 static bool isSignalPropertyName(const QHashedStringRef &);
301 int evaluateEnum(const QByteArray& script) const; // for QQmlCustomParser::evaluateEnum
302 const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
303 int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
304 QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler
307 typedef QQmlCompiledData::Instruction Instruction;
309 static void reset(QQmlCompiledData *);
311 void compileTree(QQmlScript::Object *tree);
314 bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
315 bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
316 bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
317 bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
318 const QQmlCompilerTypes::BindingContext &);
319 bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
320 const QQmlCompilerTypes::BindingContext &);
321 bool buildPropertyInNamespace(QQmlImportedNamespace *ns,
322 QQmlScript::Property *prop,
323 QQmlScript::Object *obj,
324 const QQmlCompilerTypes::BindingContext &);
325 bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
326 bool buildAttachedProperty(QQmlScript::Property *prop,
327 QQmlScript::Object *obj,
328 const QQmlCompilerTypes::BindingContext &ctxt);
329 bool buildGroupedProperty(QQmlScript::Property *prop,
330 QQmlScript::Object *obj,
331 const QQmlCompilerTypes::BindingContext &ctxt);
332 bool buildValueTypeProperty(QObject *type,
333 QQmlScript::Object *obj,
334 QQmlScript::Object *baseObj,
335 const QQmlCompilerTypes::BindingContext &ctxt);
336 bool buildListProperty(QQmlScript::Property *prop,
337 QQmlScript::Object *obj,
338 const QQmlCompilerTypes::BindingContext &ctxt);
339 bool buildScriptStringProperty(QQmlScript::Property *prop,
340 QQmlScript::Object *obj,
341 const QQmlCompilerTypes::BindingContext &ctxt);
342 bool buildPropertyAssignment(QQmlScript::Property *prop,
343 QQmlScript::Object *obj,
344 const QQmlCompilerTypes::BindingContext &ctxt);
345 bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
346 QQmlScript::Object *obj,
347 QQmlScript::Value *value,
348 const QQmlCompilerTypes::BindingContext &ctxt);
349 bool buildPropertyOnAssignment(QQmlScript::Property *prop,
350 QQmlScript::Object *obj,
351 QQmlScript::Object *baseObj,
352 QQmlScript::Value *value,
353 const QQmlCompilerTypes::BindingContext &ctxt);
354 bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
355 QQmlScript::Object *obj,
356 QQmlScript::Value *value,
357 const QQmlCompilerTypes::BindingContext &ctxt);
358 bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
359 bool testLiteralAssignment(QQmlScript::Property *prop,
360 QQmlScript::Value *value);
361 bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
362 QQmlScript::Object *obj,
363 QQmlScript::Value *value,
365 enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
366 bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
367 bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
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 compileAlias(QFastMetaBuilder &,
376 QQmlScript::Object *obj,
377 int propIndex, int aliasIndex,
378 QQmlScript::Object::DynamicProperty &);
379 bool completeComponentBuild();
380 bool checkValidId(QQmlScript::Value *, const QString &);
383 void genObject(QQmlScript::Object *obj);
384 void genObjectBody(QQmlScript::Object *obj);
385 void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
386 void genComponent(QQmlScript::Object *obj);
387 void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
388 void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
389 void genPropertyAssignment(QQmlScript::Property *prop,
390 QQmlScript::Object *obj,
391 QQmlScript::Property *valueTypeProperty = 0);
392 void genLiteralAssignment(QQmlScript::Property *prop,
393 QQmlScript::Value *value);
394 void genBindingAssignment(QQmlScript::Value *binding,
395 QQmlScript::Property *prop,
396 QQmlScript::Object *obj,
397 QQmlScript::Property *valueTypeProperty = 0);
398 int genContextCache();
400 QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
401 QQmlScript::Property *valueTypeProp);
403 int componentTypeRef();
404 int translationContextIndex();
406 static QQmlType *toQmlType(QQmlScript::Object *from);
407 bool canCoerce(int to, QQmlScript::Object *from);
409 QString elementName(QQmlScript::Object *);
411 QStringList deferredProperties(QQmlScript::Object *);
413 QQmlPropertyData *property(QQmlScript::Object *, int);
414 QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
415 bool *notInRevision = 0);
416 QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
417 bool *notInRevision = 0);
418 int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
419 int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
420 int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
422 void addId(const QString &, QQmlScript::Object *);
426 void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
428 QQmlCompilerTypes::ComponentCompileState *compileState;
432 QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
433 void saveComponentState();
435 QList<QQmlError> exceptions;
436 QQmlCompiledData *output;
438 QQmlEnginePrivate *enginePrivate;
439 QQmlScript::Object *unitRoot;
441 int cachedComponentTypeRef;
442 int cachedTranslationContextIndex;
444 // Compiler component statistics. Only collected if QML_COMPILER_STATS=1
447 ComponentStat() : ids(0), objects(0) {}
452 QList<QQmlScript::LocationSpan> scriptBindings;
453 QList<QQmlScript::LocationSpan> sharedBindings;
454 QList<QQmlScript::LocationSpan> optimizedBindings;
457 struct ComponentStats : public QQmlPool::Class
459 ComponentStat componentStat;
460 QList<ComponentStat> savedComponentStats;
462 ComponentStats *componentStats;
467 #endif // QQMLCOMPILER_P_H