v8::ObjectTemplate::SetAccessor 和 v8::Template::Set - 区别

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

我对 V8 ObjectTemplate 的 Set 和 SetAccessor 方法之间的区别感到困惑。我的问题有一个简单的 context4 个具体的子问题 .

上下文

假设我有一个代码片段想要向目标 JS 上下文提供一个全局对象 globalglobal有一个属性x,其值取int值。 global还有一个属性log,这是一个函数。所有片段均取自 V8 的源代码,准确地说是 process.cc and 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。然后从 Embedder's Guide to accessors 中,它说

An accessor is a C++ callback that calculates and returns a value when an object property is accessed by a JavaScript script. Accessors are configured through an object template, using the SetAccessor method.

代码片段如下:

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 方法,而是继承自父 class Template。从模板的 source code,它说:

/**
 * 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. Template的Set方法说可以给模板的实例设置一个原始值,那么我可以用Set在里面设置x吗第二个代码片段而不是使用 SetAccessor?

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

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

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

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

在此先感谢您的努力!

1. 是.

2. Set 是以下的 C++ 等价物(取模 属性 属性):

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

SetAccessor 是 C++ 等效于:

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

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

3. n/a

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