V8 コンテキストにアタッチする関数 AttachToContext を持つクラス「V8BaseClass」を作成したいと考えています。このクラスでは、プロトタイプとインスタンス テンプレートを使用して仮想関数 AttachAdditionalMembers を呼び出し、後継クラスがメンバーを追加できるようにします。コードの主要部分は次のようになります。
void V8BaseClass::AttachToContext(v8::Handle<v8::Context> context)
{
//working in this scope under this context.
v8::Context::Scope scopedContext(context);
//create a pointer to a class template
v8::Handle<v8::FunctionTemplate> bs_templ = v8::FunctionTemplate::New();
//assign the "bsInfo" name to the new class template (this is the name of the JS class not the name of the JS instance.)
bs_templ->SetClassName(v8::String::New("bsInfo"));
//access the class prototype template
v8::Handle<v8::ObjectTemplate> bs_proto = bs_templ->PrototypeTemplate();
//access the instance pointer of our new class template
v8::Handle<v8::ObjectTemplate> bs_inst = bs_templ->InstanceTemplate();
//set the internal fields of the class as we have the BsInfo class internally
bs_inst->SetInternalFieldCount(1);
//Attached the m_result var of the class with a result member in JS.
bs_inst->SetAccessor(v8::String::New("result"), JSGetResult, JSSetResult);
/* ==rg== just for testing reason... */
std::vector<std::string> tempVec;
tempVec.push_back("one");
tempVec.push_back("two");
bs_proto->Set("tempVec", cvv8::CastToJS(tempVec));// <== this is working fine.
/* <<< ==rg== */
//Call the inherited class method.
AttachAdditionalMembers(bs_proto, bs_inst);//<== calling the virtual function
//get the constructor function
v8::Handle<v8::Function> bs_ctor = bs_templ->GetFunction();
//get class instance
m_obj = bs_ctor->NewInstance();
//build the "bridge" between c++ and javascript by associating the bsInfo to `this` class.
m_obj->SetInternalField(0, v8::External::New(this));
//associates our internal field pointing to `this` with the "BsInfo" name inside the context
//this enable usage of BsInfo inside this context without need to create a new one
context->Global()->Set(v8::String::New("BsInfo"), m_obj);
}
後継クラスは次のようになります。
class V8Extend : public V8BaseClass
{
public:
std::vector<std::string> m_conversionTags;
std::map<std::string, std::string> m_scripts;
std::map<std::string, std::string> m_tokens;
std::map<std::string, std::string> m_urlTokens;
private:
inline virtual void AttachAdditionalMembers(const v8::Handle<v8::ObjectTemplate>& proto, const v8::Handle<v8::ObjectTemplate>& inst)
{
//set test data:
m_conversionTags.push_back("conversion1");
m_conversionTags.push_back("conversion2");
m_conversionTags.push_back("conversion3");
m_scripts["script1"] = "This is script1!";
m_scripts["script2"] = "This is script2!";
m_scripts["script3"] = "This is script3!";
m_tokens["T1"] = "Token1";
m_tokens["T2"] = "Token2";
m_urlTokens["UT1"] = "UT-1";
m_urlTokens["UT2"] = "UT-2";
//end of setting test data.
proto->Set("conversionTags", cvv8::CastToJS(m_conversionTags));//<==throwing exception
proto->Set("tokens", cvv8::CastToJS(m_tokens));
proto->Set("scripts", cvv8::CastToJS(m_scripts));
proto->Set("urlTokens", cvv8::CastToJS(m_urlTokens));
};
};
この呼び出しは、基本クラスから呼び出されたときに正常に機能し、後続クラスから呼び出されたときに失敗したのはなぜですか?
==編集==これが役立つ場合は、例外が呼び出されたときのコールスタックです:
ModuleManagementTest.exe!v8::internal::FixedArrayBase::length() Line 2188 + 0xe bytes C++
ModuleManagementTest.exe!v8::internal::FixedArray::get(int index=3) Line 1661 + 0x11 bytes C++
ModuleManagementTest.exe!v8::internal::Context::global() Line 324 + 0xf bytes C++
ModuleManagementTest.exe!v8::internal::Context::global_context() Line 62 + 0xa bytes C++
ModuleManagementTest.exe!v8::internal::Heap::AllocateJSArray(v8::internal::ElementsKind elements_kind=FAST_ELEMENTS, v8::internal::PretenureFlag pretenure=NOT_TENURED) Line 4412 + 0x1a bytes C++
ModuleManagementTest.exe!v8::internal::Heap::AllocateJSArrayAndStorage(v8::internal::ElementsKind elements_kind=FAST_ELEMENTS, int length=0, int capacity=3, v8::internal::ArrayStorageAllocationMode mode=INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, v8::internal::PretenureFlag pretenure=NOT_TENURED) Line 3838 + 0x13 bytes C++
ModuleManagementTest.exe!v8::internal::Factory::NewJSArray(int capacity=3, v8::internal::ElementsKind elements_kind=FAST_ELEMENTS, v8::internal::PretenureFlag pretenure=NOT_TENURED) Line 958 + 0x62 bytes C++
ModuleManagementTest.exe!v8::Array::New(int length=3) Line 5012 C++
ModuleManagementTest.exe!cvv8::NativeToJS_list<std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >::operator()(const std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > & li=[3]("conversion1","conversion2","conversion3")) Line 1453 + 0xe bytes C++
ModuleManagementTest.exe!cvv8::CastToJS<std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >(const std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > & v=[3]("conversion1","conversion2","conversion3")) Line 444 + 0x14 bytes C++
ModuleManagementTest.exe!V8Extend::AttachAdditionalMembers(const v8::Handle<v8::ObjectTemplate> & proto={...}, const v8::Handle<v8::ObjectTemplate> & inst={...}) Line 43 + 0x2c bytes C++
v8::internal::FixedArray::get(int index=3)
アサート行の関数で失敗しますASSERT(index >= 0 && index < this->length());
==編集 2== V8BaseClass に「AttachAdditionalMembers」関数を実装しようとしましたが、同じ問題が発生しましたが、関数を変更するとうまくいきませんでしvirtual
た。
何か案は???