当前位置: 代码迷 >> 综合 >> qtdeclarative 源码略读
  详细解决方案

qtdeclarative 源码略读

热度:44   发布时间:2023-12-16 09:07:41.0

qtdeclarative 源码略读

如果想使用 qtdeclarative 中一些私有接口的话,请在 pro 文件中添加这么一句:QT += qml-private core-private。这样也可以在 QtCreator 中阅读 qtdeclarative 代码。

ECMAScript 解析器

其实就是编译原理这一块。源码路径为 qtdeclarative\src\qml\parser

其实 QML 本身就是一种 ECMAScript,所以这个语法分析器是在解析 ECMAScript 的基础上,顺带解析 qml 的。

enum Kind {Kind_Undefined,Kind_ArgumentList,Kind_ArrayLiteral,Kind_ArrayMemberExpression,
...Kind_UiHeaderItemList};

以上为语法树节点的类型,其中 Kind_UI* 就是 QML 文档中的 Token

qqmljsast_p.h           ==> ast 抽象语法树   
qqmljsastfwd_p.h        ==> 前置声明的头文件
qqmljsastvisitor_p.h    ==> 语法树节点访问器
qqmljsengine_p          ==> 语法解析引擎
qqmljsglobal_p.h        ==> 全局定义
qqmljsgrammar_p.h       ==> 语法的一些定义
qqmljskeywords_p.h      ==> 关键词
qqmljslexer_p.h         ==> 分词器
qqmljsmemorypool_p.h    ==> 语法分析过程中的内存分配器
qqmljsparser_p.h        ==> 语法分析和制导生成语法树

大体如此。

QV4

这里讲一讲 QV4 这个名字空间下的一些类和一些类型。

namespace QV4 {namespace Heap {struct Base;                    // 包含一个共用体,共用体有 `QV4::ManagedVTable` 以及一个 `quintptr` 。struct MemberData;struct ArrayData;struct String;struct Object;struct ObjectPrototype;struct ExecutionContext;struct GlobalContext;struct CallContext;struct ScriptFunction;struct BooleanObject;struct NumberObject;struct StringObject;struct ArrayObject;struct DateObject;struct FunctionObject;struct ErrorObject;struct ArgumentsObject;struct QObjectWrapper;struct RegExpObject;struct RegExp;struct EvalFunction;struct ArrayBuffer;struct DataView;struct TypedArray;}class MemoryManager;
struct String;
struct Object;
struct ObjectPrototype;
struct ObjectIterator;
struct ExecutionContext;            // 继承自引擎上下文(例如可以获取函数参数,调用函数的对象)。
struct GlobalContext;
struct CallContext;
struct ScriptFunction;
struct InternalClass;
struct Property;
struct Value;                       // 用来保存 `JS` 变量,包含一个共用体,// 可能保存一个数值,一个浮点数,一个上下文 `QV4::Heap::Base`,// 其中的 `tag` 为 `Value::ValueType` 类型。
struct Lookup;
struct ArrayData;
struct ManagedVTable;               // 托管`JS` 变量对象的上下文,或者说是一个对象的虚表。struct BooleanObject;
struct NumberObject;
struct StringObject;
struct ArrayObject;
struct DateObject;
struct FunctionObject;
struct ErrorObject;
struct ArgumentsObject;
struct Managed;                     // 继承自 `QV4::Value` 字面意思应该是托管一个 `JS` 变量的类。// 一般用来托管一个函数或者一个对象。
struct ExecutionEngine;             // 执行 `JavaScirpt` 或者 `QML` 的执行引擎。
struct QObjectWrapper;
struct RegExpObject;
struct RegExp;
struct EvalFunction;struct ArrayBuffer;
struct DataView;
struct TypedArray;// ReturnedValue is used to return values from runtime methods
// the type has to be a primitive type (no struct or union), so that the compiler
// will return it in a register on all platforms.
// It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm
typedef quint64 ReturnedValue;struct CallData;                // 函数调用的参数以及其他栈信息。
struct Scope;                   // 上下文的作用域,或者引擎的执行栈栈顶。
struct ScopedValue;             // 上下文的作用域中,位于引擎的执行栈栈顶的变量。
template<typename T> struct Scoped;    // 是 `QV4::Managed*` 的指针帮助类。传入一个 `QV4::Managed` 或者其子裔。
typedef Scoped<String> ScopedString;
typedef Scoped<Object> ScopedObject;
typedef Scoped<ArrayObject> ScopedArrayObject;
typedef Scoped<FunctionObject> ScopedFunctionObject;
typedef Scoped<ExecutionContext> ScopedContext;struct PersistentValueStorage;
class PersistentValue;
class WeakValue;struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
struct QmlExtensions;namespace Global {enum {ReservedArgumentCount = 6};
}enum PropertyFlag {Attr_Data = 0,Attr_Accessor = 0x1,Attr_NotWritable = 0x2,Attr_NotEnumerable = 0x4,Attr_NotConfigurable = 0x8,Attr_ReadOnly = Attr_NotWritable|Attr_NotEnumerable|Attr_NotConfigurable,Attr_Invalid = 0xff
};Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(PropertyFlags)struct PropertyAttributes;                          // 属性对象的定义struct StackFrame {QString source;QString function;int line;int column;
};
typedef QVector<StackFrame> StackTrace;}

向 QV4::ExecutionEngine 注册一些类型

现在取 Number 的注册过程来叙述。

代码在 qtdeclarative\src\qml\jsruntime\qv4numberobject_p.hqtdeclarative\src\qml\jsruntime\qv4numberobject.cpp

namespace QV4 {
namespace Heap {
struct NumberCtor : FunctionObject {NumberCtor(QV4::ExecutionContext *scope);
};
}
...

先定义了一个继承自 QV4::Heap::FunctionObject 的对象 QV4::Heap::NumberCtor,有关于 QV4::Heap 的东西,大体就是用来动态构建和进行垃圾回收的。

struct NumberCtor: FunctionObject
{V4_OBJECT2(NumberCtor, FunctionObject)static ReturnedValue construct(Managed *that, CallData *callData);static ReturnedValue call(Managed *, CallData *callData);
};

在定义了一个 QV4::NumberCtor,声明了构造器和 call


struct NumberPrototype: NumberObject {void init(ExecutionEngine *engine, Object *ctor);static ReturnedValue method_toString(CallContext *ctx);static ReturnedValue method_toLocaleString(CallContext *ctx);static ReturnedValue method_valueOf(CallContext *ctx);static ReturnedValue method_toFixed(CallContext *ctx);static ReturnedValue method_toExponential(CallContext *ctx);static ReturnedValue method_toPrecision(CallContext *ctx);
};
} // QV4

定义了 Number 对象的原型(方法列表),以及一个初始化函数。

void NumberPrototype::init(ExecutionEngine *engine, Object *ctor) {Scope scope(engine);ScopedObject o(scope);ctor->defineReadonlyProperty(engine->id_prototype, (o = this));ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qSNaN()));ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));ctor->defineReadonlyProperty(QStringLiteral("POSITIVE_INFINITY"), Primitive::fromDouble(qInf()));ctor->defineReadonlyProperty(QStringLiteral("MAX_VALUE"), Primitive::fromDouble(1.7976931348623158e+308));defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));defineDefaultProperty(engine->id_toString, method_toString);...
}

查看 NumberPrototype::init(ExecutionEngine *engine, Object *ctor) 函数,通过构造 scope 来获取 ExecutionEngine 的作用域和上下文,然后构造一个 ScopedObject 帮助类,为传入的 ctor 设置只读的原型字段(属性)为 NumberPrototype,其他一些字段或者常量,然后调用本身的 defineDefaultProperty 设置一些方法例如构造器和方法。

ExecutionEngine 构造函数中注册 Number

    // numberCtor ==> QV4::ValueScope scope(this); // this is ExecutionEngineScopedContext global(scope, rootContext());numberCtor = memoryManager->alloc<NumberCtor>(global);static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);

QV8Engine

源码 qtdeclarative\src\qml\qml\v8qtdeclarative\src\qml\qml

QV8Engine 的主要结构如下:

//~QV8EngineQtObject {property QJSEngine qproperty QQmlEngine m_engineQV4::ExecutionEngine {id: v4engine}
}

只有在 QQmlEngine 中才会调用 QV8Engine::setEngine(QQmlEngine *engine),向 QML 的上下文注册全局对象 consoleQtXMLHttpRequest 等全局对象。

QJSEngine 中不会调用 QV8Engine::setEngine(QQmlEngine *engine)

  相关解决方案