V8继承了FunctionTemplate,没有获得父FunctionTemplate的更新

时间:2015-01-21 20:38:14

标签: c++ inheritance v8

我正在使用V8为应用程序添加JavaScript支持。由于各种原因我无法进入,我们需要能够向FunctionTemplate添加方法,并让这些方法出现在已经从它继承的任何FunctionTemplates中。

例如,

v8::Handle<v8::FunctionTemplate> parent;
v8::Handle<v8::FunctionTemplate> child;
child->Inherit(parent);
parent->PrototypeTemplate()->Set(isolate, "someNewMethod", v8::FunctionTemplate::New(...));

不幸的是,我发现当父母被修改时,孩子们只有继承时可用的方法,而且,即使我告诉孩子从父母那里重新学习,仍然没有获得新的方法。

更糟糕的是,如果我有这样的关系:

v8::FunctionTemplate parent, firstChild;
firstChild->Inherit(parent);
parent->PrototypeTemplate()->Set(isolate, "newMethod", FunctionTemplate::New(...));
v8::FunctionTemplate secondChild;
secondChild->Inherit(parent);

然后secondChild的实例仍然只有[{1}}继承parent时可用的firstChild方法。

据我所知,V8可能会积极地优化继承关系;从子FunctionTemplate实例化的对象不显示原型链,而只是将方法直接绑定到它们。所以,我认为我需要使用Object::SetPrototype来代替这一点,但我在此处所做的每一次尝试都会导致V8崩溃,创建一个原型链,其中没有任何继承的方法可见,或者具有与FunctionTemplate::Inherit案例相同的有效行为。

在V8中提供继承方法的可接受标准机制是什么,可以将本机方法添加到超类中?

2 个答案:

答案 0 :(得分:2)

一旦实际Function已从FunctionTemplate实例化,FunctionTemplate的其他更改将不再反映在派生对象中。因此,一旦调用InheritNewInstance,您就无法更改附加到基础FunctionTemplate的方法。

但是,还有另一种方法可以做到这一点:对于每个本地类,都有一个FunctionTemplate,然后是一个代理Object,可以直接在原型链中使用。例如,

v8::Handle<v8::FunctionTemplate> base_tmpl;
v8::Handle<v8::Object> base_proto = base_tmpl->GetFunction()->NewInstance();
v8::Handle<v8::FunctionTemplate> derived_tmpl;
v8::Handle<v8::Object> derived_proto = derived_tmpl->GetFunction()->NewInstance();
derived_proto->SetPrototype(base_proto);

base_proto->Set("methodName", v8::FunctionTemplate::New(...)->GetFunction());

然后,当您想要实例化一个对象时,您可以:

v8::Handle<v8::ObjectTemplate> instance_tmpl;
instance_tmpl->SetInternalFieldCount(1);
v8::Handle<v8::Object> instance = instance_tmpl->NewInstance();
instance->SetInternalField(0, nativeObject);
instance->SetPrototype(derived_proto);

从技术上讲,您只需要实例代理Object,但仍然使用FunctionTemplate允许您使用其SetClassName(对调试很有用)以及{{1 (用于运行时类型检查等)。

答案 1 :(得分:0)

我的经历似乎与你的不同。我确实可以在原型上设置方法,并且它们可以通过继承获得,即使在对孩子调用FunctionTemplate::Inherit之后添加方法时也是如此。

我的工作测试的完整来源是here,但总结一下......

我创建了parent类,就像这样......

v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
t->SetClassName(v8::String::NewFromUtf8(isolate, "A_Parent"));
auto proto = t->PrototypeTemplate();
proto->Set(v8::String::NewFromUtf8(isolate, "methodA"), v8::FunctionTemplate::New(isolate, MethodACallback));

然后是继承的child类......

v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
t->SetClassName(v8::String::NewFromUtf8(isolate, "A_Child"));
t->Inherit(parent);
auto proto = parent->PrototypeTemplate();
proto->Set(v8::String::NewFromUtf8(isolate, "methodB"), v8::FunctionTemplate::New(isolate, MethodBCallback));
// MethodACallback and MethodBCallback just contain a simple std::cout statement.

(您会注意到我在methodB继承child后)我正在添加parent

然后我导入A_Child函数导入全局上下文...

ctx->Global()->Set(v8::String::NewFromUtf8(isolate, "A_Child"), child->GetFunction());

...并编译/运行以下脚本......

"use strict";

var c = new A_Child();

c.methodA();
c.methodB();

哪些输出......

methodA called from [object A_Child]
methodB called from [object A_Child]

我正在使用v8 4.2.0并使用clang 3.3进行编译。在OS X 10.8.5上运行