WebKit中爲JS binding擴展DOM對象

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章