v8::ObjectTemplate::SetAccessor 和 v8::Template::Set - 区别
v8::ObjectTemplate::SetAccessor and v8::Template::Set - Difference
我对 V8 ObjectTemplate 的 Set 和 SetAccessor 方法之间的区别感到困惑。我的问题有一个简单的 context 和 4 个具体的子问题 .
上下文
假设我有一个代码片段想要向目标 JS 上下文提供一个全局对象 global
。 global
有一个属性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);
问题
Template的Set方法说可以给模板的实例设置一个原始值,那么我可以用Set在里面设置x
吗第二个代码片段而不是使用 SetAccessor?
如果问题 1 的答案是正确的,那么设置 x
与使用 SetMethod
和 Set
有什么区别?不同之处在于,在 JS 中对 Set
设置的 属性 的任何修改都不会反映在 C++ 中吗?
如果问题 1 的答案是错误的,那为什么我不能在 X
上使用 Set?
从访问器的描述来看,它说它计算 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任何你想要的值;特别是该值可以是一个函数。
我对 V8 ObjectTemplate 的 Set 和 SetAccessor 方法之间的区别感到困惑。我的问题有一个简单的 context 和 4 个具体的子问题 .
上下文
假设我有一个代码片段想要向目标 JS 上下文提供一个全局对象 global
。 global
有一个属性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);
问题
Template的Set方法说可以给模板的实例设置一个原始值,那么我可以用Set在里面设置
x
吗第二个代码片段而不是使用 SetAccessor?如果问题 1 的答案是正确的,那么设置
x
与使用SetMethod
和Set
有什么区别?不同之处在于,在 JS 中对Set
设置的 属性 的任何修改都不会反映在 C++ 中吗?如果问题 1 的答案是错误的,那为什么我不能在
X
上使用 Set?从访问器的描述来看,它说它计算 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任何你想要的值;特别是该值可以是一个函数。