v8::ObjectTemplate::SetAccessor and v8::Template::Set - Diff

v8::ObjectTemplate::SetAccessor and v8::Template::Set - Difference

本文关键字:v8 Diff Set and ObjectTemplate SetAccessor Template      更新时间:2023-10-16

我对V8 ObjectTemplate的Set和SetAccessor方法之间的差异感到困惑。我的问题有一个简单的上下文4 个具体的子问题

上下文

假设我有代码片段想要提供对目标 JS 上下文global的全局对象。global有一个属性x,其值取 int 值。global还有一个属性log,这是一个函数。所有片段都取自 V8 的源代码,准确地说是 process.cc 和 Embedder's Guide。

HandleScope handle_scope(GetIsolate());    
// Create a template for the global object where we set the
// built-in global functions.
Local<ObjectTemplate> global = ObjectTemplate::New(GetIsolate());
global->Set(String::NewFromUtf8(GetIsolate(), "log", 
NewStringType::kNormal).ToLocalChecked(),
FunctionTemplate::New(GetIsolate(), LogCallback));

因此,此代码片段提供了对全局的函数log。然后从嵌入者指南到访问器,它说

访问器是一个C++回调,当 JavaScript 脚本访问对象属性时,它计算并返回值。访问器是使用 SetAccessor 方法通过对象模板配置的。

代码片段如下:

void XGetter(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
info.GetReturnValue().Set(x);
}
void XSetter(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<Value>& info) {
x = value->Int32Value();
}
// YGetter/YSetter are so similar they are omitted for brevity
Local<ObjectTemplate> global_templ = ObjectTemplate::New(isolate);
global_templ->SetAccessor(String::NewFromUtf8(isolate, "x"), XGetter, XSetter);
global_templ->SetAccessor(String::NewFromUtf8(isolate, "y"), YGetter, YSetter);
Persistent<Context> context = Context::New(isolate, NULL, global_templ);

据我了解,这个代码片段在描述中提供了一些x全局的整数值。

现在,从 V8 的源代码中,我看到 ObjectTemplate 没有 Set 方法,相反,它是从父类 Template 继承而来的。从模板的源代码中,它说:

/**
* Adds a property to each instance created by this template.
*
* The property must be defined either as a primitive value, or a template.
*/
void Set(Local<Name> name, Local<Data> value,
propertyAttribute attributes = None);

问题

  1. 模板的 Set 方法说它可以为模板的实例设置一个基元值,那么我可以使用 Set在第二个代码片段中设置x而不是使用 SetAccessor 吗?

  2. 如果问题 1 的答案是正确的,那么使用SetMethodSet之间设置x有什么区别?区别在于 JS 中对Set设置的属性的任何修改都不会反映在C++中吗?

  3. 如果问题 1 的答案是假的,那么为什么我不能在X上使用 Set ?

  4. 从访问器的描述来看,它说它计算并返回。那么这是否意味着我们不使用SetAccessor来返回函数?我很困惑,因为我主要写JS和Haskell。这两种语言都宠坏了我把函数当作价值观。

现在我知道通过实际构建样本来验证我的所有假设应该很容易,但我在编译 V8 源代码时遇到困难,因此我寻求任何帮助。

提前感谢您的任何努力!

1.是的。

2.Set是以下各项的C++等效(模属性属性):

Object.defineProperty(global, "x", {value: 3})

SetAccessorC++等效于:

Object.defineProperty(global, "x", {get: function XGetter() { return ...; }, 
set: function XSetter(val) { ... }});

正如你所建议的,结果是,在Set的情况下,C++端无法知道值是否从JavaScript端更改。

3.不适用

4.getter 可以返回任何你想要的值;特别是这个值可以是一个函数。