DOM对象有三种形态
一.寄生于现有对象,单实例
从属于某个全局变量,访问时通过宿主对象完成。如window.object,也可以直接调用object.method。这个方法最为简单,按需分配,并且随着宿主对象释放。参考window的Navigator实现。
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>
二.和window、document一样成为全局变量,单实例。
这个实现最为复杂,关键要将对象在合适的位置创建,并更新到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.txt和WebCore.gypi参考Document.idl Document.h Document.cpp JSDocument.cpp 添加相应内容。
三.多实例对象。可以在脚本中使用new创建。
myObj = new Object();
较第一类需要指定自定义建构函数,主要参考DOM中的Image和Float32Array实现。