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;
添加头文件:
- #include "CooperWebObject.h"
- CooperWebObject* DOMWindow::CooperWebObject()const
- {
- if (!m_cooperWebObject)
- m_cooperWebObject = CooperWebObject::create();
- return m_cooperWebObject.get();
- }
- m_cooperWebObject = 0;
- attribute [Replaceable] CooperWebObject cooperWebObject;
- $(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"
- 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"
- 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实现。