WebKit之addToJavaScriptWindowObject()分析

本文介绍了Qt中通过QWebFrameAdapter将QObject暴露给JSC引擎的方法,详细展示了相关API的实现源码,并探讨了Qt如何基于JSC的bridge实例进行继承与扩展。

## Qt暴露QObject给JSC引擎的API源码

void QWebFrameAdapter::addToJavaScriptWindowObject(const QString& name, QObject* object, ValueOwnership ownership)
{
    if (!pageAdapter->settings->testAttribute(QWebSettings::JavascriptEnabled))
        return;
    JSC::Bindings::QtInstance::ValueOwnership valueOwnership = static_cast<JSC::Bindings::QtInstance::ValueOwnership>(ownership);
    JSDOMWindow* window = toJSDOMWindow(frame, mainThreadNormalWorld());
    JSC::Bindings::RootObject* root;
    if (valueOwnership == JSC::Bindings::QtInstance::QtOwnership)
        root = frame->script()->cacheableBindingRootObject();
    else
        root = frame->script()->bindingRootObject();

    if (!window) {
        qDebug() << "Warning: couldn't get window object";
        return;
    }
    if (!root) {
        qDebug() << "Warning: couldn't get root object";
        return;
    }

    JSC::ExecState* exec = window->globalExec();
    JSC::JSLockHolder lock(exec);

    JSC::JSObject* runtimeObject = JSC::Bindings::QtInstance::getQtInstance(object, root, valueOwnership)->createRuntimeObject(exec);

    JSC::PutPropertySlot slot;
    window->methodTable()->put(window, exec, JSC::Identifier(&exec->vm(), reinterpret_cast_ptr<const UChar*>(name.constData()), name.length()), runtimeObject, slot);
}


##   JSC桥实例的创建源码

#include "config.h"
#include "BridgeJSC.h"

#include "JSDOMWindowBase.h"
#include "runtime_object.h"
#include "runtime_root.h"
#include "runtime/JSLock.h"
#include "runtime/ObjectPrototype.h"


#if PLATFORM(QT)
#include "qt_instance.h"
#endif

namespace JSC {

namespace Bindings {

Array::Array(PassRefPtr<RootObject> rootObject)
    : m_rootObject(rootObject)
{
    ASSERT(m_rootObject);
}

Array::~Array()
{
}

Instance::Instance(PassRefPtr<RootObject> rootObject)
    : m_rootObject(rootObject)
{
    ASSERT(m_rootObject);
}

Instance::~Instance()
{
    ASSERT(!m_runtimeObject);
}

void Instance::begin()
{
    virtualBegin();
}

void Instance::end()
{
    virtualEnd();
}

JSObject* Instance::createRuntimeObject(ExecState* exec)
{
    ASSERT(m_rootObject);
    ASSERT(m_rootObject->isValid());
    if (RuntimeObject* existingObject = m_runtimeObject.get())
        return existingObject;

    JSLockHolder lock(exec);
    RuntimeObject* newObject = newRuntimeObject(exec);
    m_runtimeObject = PassWeak<RuntimeObject>(newObject);
    m_rootObject->addRuntimeObject(exec->vm(), newObject);
    return newObject;
}

RuntimeObject* Instance::newRuntimeObject(ExecState* exec)
{
    JSLockHolder lock(exec);

    // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
    // We need to pass in the right global object for "i".
    return RuntimeObject::create(exec, exec->lexicalGlobalObject(), WebCore::deprecatedGetDOMStructure<RuntimeObject>(exec), this);
}

void Instance::willInvalidateRuntimeObject()
{
    m_runtimeObject.clear();
}

RootObject* Instance::rootObject() const
{
    return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
}

## Qt基于JSC内定的bridge实例进行继承和扩展(为qt平台方便访问)

class QtInstance : public Instance {
public:
    enum ValueOwnership {
        QtOwnership,
        ScriptOwnership,
        AutoOwnership
    };

    ~QtInstance();

    virtual Class* getClass() const;
    virtual RuntimeObject* newRuntimeObject(ExecState*);

    virtual void begin();
    virtual void end();

    virtual JSValue valueOf(ExecState*) const;
    virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;

    virtual JSValue getMethod(ExecState*, PropertyName);
    virtual JSValue invokeMethod(ExecState*, RuntimeMethod*);

    virtual void getPropertyNames(ExecState*, PropertyNameArray&);

    JSValue stringValue(ExecState* exec) const;
    JSValue numberValue(ExecState* exec) const;
    JSValue booleanValue() const;

    QObject* getObject() const { return m_object.data(); }
    QObject* hashKey() const { return m_hashkey; }

    static PassRefPtr<QtInstance> getQtInstance(QObject*, PassRefPtr<RootObject>, ValueOwnership);

    virtual bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
    virtual void put(JSObject*, ExecState*, PropertyName, JSValue, PutPropertySlot&);

    static QtInstance* getInstance(JSObject*);

private:
    static PassRefPtr<QtInstance> create(QObject *instance, PassRefPtr<RootObject> rootObject, ValueOwnership ownership)
    {
        return adoptRef(new QtInstance(instance, rootObject, ownership));
    }

    friend class QtClass;
    friend class QtField;
    friend class QtRuntimeMethod;
    QtInstance(QObject*, PassRefPtr<RootObject>, ValueOwnership); // Factory produced only..
    mutable QtClass* m_class;
    QPointer<QObject> m_object;
    QObject* m_hashkey;
    mutable QHash<QByteArray, QtRuntimeMethod*> m_methods;
    mutable QHash<QString, QtField*> m_fields;
    ValueOwnership m_ownership;
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值