V8 继承的 FunctionTemplate 没有得到对父 FunctionTemplate 的更新

V8 inherited FunctionTemplate not getting updates to the parent FunctionTemplate

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

例如,

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 的实例仍然只有在 firstChild 继承时可用的 parent 方法。

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

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

似乎一旦 FunctionFunctionTemplate 实例化,对 FunctionTemplate 的其他更改就不再反映在派生对象中。因此,一旦发生对 InheritNewInstance 的调用,您就无法更改附加到基础 FunctionTemplate.

的方法

然而,还有另一种方法可以做到这一点:对于每个原生 class,都有一个 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);

从技术上讲,您只需实例化代理 Objects,但仍然拥有 FunctionTemplate 允许您利用其 SetClassName(对调试有用)以及 Object::FindInstanceInPrototypeChain(对于 运行-time 类型检查等很有用)。

我的经历似乎与你的不同。我确实可以在原型上设置方法,并且它们可以通过继承使用,即使在对子对象调用 FunctionTemplate::Inherit 之后添加了这些方法。

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

我像这样创建了 parent class …

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));

然后继承childclass...

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.

(你会注意到这里我在child继承parent之后添加了methodB

然后我将 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