WebKit中为JS binding扩展DOM对象

来源:互联网 发布:程序员几月份好找工作 编辑:程序博客网 时间:2024/05/20 20:21

DOM对象有三种形态

一.寄生于现有对象,单实例

从属于某个全局变量,访问时通过宿主对象完成。如window.object,也可以直接调用object.method。这个方法最为简单,按需分配,并且随着宿主对象释放。参考windowNavigator实现。

1、添加CooperWebObject.h, CooperWebObject.cpp, CooperWebObject.idl文件,简单起见,将这三个文件放到Source/WebCore/page目录下。

a. CooperWebObject.h

#ifndef CooperWebObject_h#define CooperWebObject_h#include <wtf/Forward.h>#include <wtf/HashMap.h>#include <wtf/PassRefPtr.h>#include <wtf/RefCounted.h>#include <wtf/RefPtr.h>namespace WebCore{class CooperWebObject : public RefCounted<CooperWebObject>{public:static PassRefPtr<CooperWebObject> create( ){return adoptRef( new CooperWebObject() );}String description() const;private:CooperWebObject();};}//namespace WebCore#endif

b. CooprWebObject.cpp

#include "config.h"#include "CooperWebObject.h"namespace WebCore{CooperWebObject::CooperWebObject(){//construction}String CooperWebObject::description() const{return "Hello World!";}}//namespace WebCore

c. CooperWebObject.idl

[    OmitConstructor] interface CooperWebObject {    readonly attribute DOMString description;};

也可以通过idl文件手动去生成相关的文件,JSCooperWebObject.h JSCooperWebOhject.cpp。手动生成的时候需要使用到WebCore\bindings\scripts\generate-bindings.pl 这个脚本,使用的时候还需要一些参数,./generate-bindings.pl ./test/CooperWebObject.idl --generator=JS --outputDir=../js/  详细的参数说明参考 generate-bindings.pl 中的注释。WebKitIDL的使用可以参考http://trac.webkit.org/wiki/WebKitIDL 。在Windows平台上idl文件末尾需要添加一个空行,不然在生成文件的时候会提示错误。


d. 修改DOMWindow.h,添加如下代码:

class CooperWebObject;…public:    CooperWebObject* CooperWebObject() const;private:    mutable RefPtr<CooperWebObject> m_cooperWebObject;
e. 修改DOMWindow.cpp,添加如下代码:

    添加头文件:

#include "CooperWebObject.h"
    添加函数:

CooperWebObject* DOMWindow::CooperWebObject()const{    if (!m_cooperWebObject)       m_cooperWebObject = CooperWebObject::create();    return m_cooperWebObject.get();}
  在resetDOMWindowProperties()函数中添加:

m_cooperWebObject = 0;
f. 修改DOMWindow.idl,添加如下一行 :
attribute [Replaceable] CooperWebObject cooperWebObject;
g. 修改DerivedSources.make, 参考Navigator.idl添加如下代码:
$(WebCore)/page/CooperWebObject.idl \

h. 修改CMakeLists.txt和WebCore.gypi,参考Navigator.idl, Navigator.h, Navigator.cpp添加相应的文件.

I.  对于VS Project,可以将相关的文件添加项目中,然后我的是重新编译整个solution才测试成功。

测试代码:

<html> <body> <script>document.write("<p> This is from cooperWebObject: "); document.write(window.cooperWebObject.description + "</p>"); document.write("<br />");document.write(cooperWebObject.description);</script> </body> </html>

二.和windowdocument一样成为全局变量,单实例。

这个实现最为复杂,关键要将对象在合适的位置创建,并更新到JSC的堆中才能达到功能。可以参考document的实现,并且需要考虑执行流程,必须对代码做过一些了解,才可能知道相关的改动量。

因为是DOM有一个新的全局对象,将新增文件放到WebCore/dom下。

A. CooperGlobalWebObject.h

#ifndef CooperGlobalWebObject_h#define CooperGlobalWebObject_h#include <wtf/Forward.h>#include <wtf/HashMap.h>#include <wtf/PassRefPtr.h>#include <wtf/RefCounted.h>#include <wtf/RefPtr.h>#include <wtf/text/WTFString.h>namespace WebCore{class CooperGlobalWebObject : public RefCounted<CooperGlobalWebObject>{public:static PassRefPtr<CooperGlobalWebObject> create( ){return adoptRef( new CooperGlobalWebObject() );}String description() const;private:CooperGlobalWebObject();};}//namespace WebCore#endif

B. CooperGlobalWebObject.cpp

#include "config.h"#include "CooperGlobalWebObject.h"namespace WebCore{CooperGlobalWebObject::CooperGlobalWebObject(){//construction}String CooperGlobalWebObject::description() const{return "Hello World From Global Object!";}}//namespace WebCore

C. CooperGlobalWebObject.idl

[    OmitConstructor] interface CooperGlobalWebObject {    readonly attribute DOMString description;};

D. 修改DOMWindow.h,添加如下代码

class CooperGlobalWebObject;public:CooperGlobalWebObject * cooperGlobalWebObject() const;private:mutable RefPtr<CooperGlobalWebObject> m_cooperGlobalWebObject;

E. 修改DOMWindow.cpp,添加如下代码

#include "CooperGlobalWebObject.h"
在void DOMWindow::resetDOMWindowProperties()函数中添加一行

m_cooperGlobalWebObject = 0;
添加函数

CooperGlobalWebObject* DOMWindows::cooperGlobalWebObject() const{if (!m_cooperGlobalWebObject)m_cooperGlobalWebObject = CooperGlobalWebObject::create();return m_cooperGlobalWebObject.get();}

F. 修改JSDOMWindowBase.h updateDocument 下添加一行

void updateCooperGlobalWebObject();

G. 修改JSDOMWindowBase.cpp 

#include "JSCooperGlobalWebObject.h"
添加函数

void void JSDOMWindowBase::updateCooperGlobalWebObject(){ASSERT(m_impl->cooperGlobalWebObject);ExecState* exec = globalExec();symbolTablePutWithAttributes(this, exec->globalData(), Identifier(exec, "cooperglobalwebobject"), toJS(exec, this, m_impl->cooperGlobalWebObject()), DontDelete | ReadOnly);}

在finishCreation函数中的staticGlobals中添加一行

GlobalPropertyInfo(Identifier(globalExec(), "cooperglobalwebobject"), jsNull(), DontDelete | ReadOnly),

H. 修改ScriptController.h updateDocument 下添加一行

void updateCooperGlobalWebObject();

I. 修改ScriptController.cpp 

#include "CooperGlobalWebObject.h"
在updateDocument下面添加一行

windowShell->window()->updateCooperGlobalWebObject();
添加函数

void ScriptController::updateCooperGlobalWebObject(){    for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) {        JSLockHolder lock(iter->key->globalData());        iter->value->window()->updateCooperGlobalWebObject();    }}

J. 修改Frame.cpp setDocument函数中m_script.updateDocument下加入一行

m_script.updateCooperGlobalWebObject();

K. 修改DerivedSources.make,参考Document.idl添加一行

$(WebCore)/dom/CooperGlobalWebObject.idl \

L. 修改CMakeLists.txtWebCore.gypi参考Document.idl Document.h Document.cpp  JSDocument.cpp 添加相应内容。

三.多实例对象。可以在脚本中使用new创建。

myObj = new Object();

较第一类需要指定自定义建构函数,主要参考DOM中的ImageFloat32Array实现。

原创粉丝点击