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實現。